added logging facility and added a bunch of log messages.

This commit is contained in:
crs 2001-10-14 14:37:41 +00:00
parent 23f948d55a
commit 1ed2b43e13
8 changed files with 136 additions and 31 deletions

View File

@ -13,7 +13,7 @@ RMR = /bin/rm -rf
# #
# compiler options # compiler options
# #
GCXXDEFS = -D_POSIX_C_SOURCE=199309 GCXXDEFS = -D_XOPEN_SOURCE=500
GCXXINCS = -I$(DEPTH)/include -I/usr/X11R6/include GCXXINCS = -I$(DEPTH)/include -I/usr/X11R6/include
GCXXOPTS = -Wall -W -fexceptions -fno-rtti GCXXOPTS = -Wall -W -fexceptions -fno-rtti
CXXOPTIMIZER = -g CXXOPTIMIZER = -g

View File

@ -13,6 +13,7 @@ LCXXINCS = \
$(NULL) $(NULL)
CXXFILES = \ CXXFILES = \
XBase.cpp \ XBase.cpp \
CLog.cpp \
CFunctionJob.cpp \ CFunctionJob.cpp \
CStopwatch.cpp \ CStopwatch.cpp \
$(NULL) $(NULL)

View File

@ -6,7 +6,7 @@
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "CTimerThread.h" #include "CTimerThread.h"
#include "XSynergy.h" #include "XSynergy.h"
#include <stdio.h> #include "CLog.h"
#include <memory> #include <memory>
// //
@ -29,6 +29,8 @@ CClient::~CClient()
#include "CXWindowsSecondaryScreen.h" #include "CXWindowsSecondaryScreen.h"
void CClient::run(const CNetworkAddress& serverAddress) void CClient::run(const CNetworkAddress& serverAddress)
{ {
log((CLOG_DEBUG "starting client \"%s\"", m_name.c_str()));
std::auto_ptr<ISocket> socket; std::auto_ptr<ISocket> socket;
std::auto_ptr<IInputStream> input; std::auto_ptr<IInputStream> input;
std::auto_ptr<IOutputStream> output; std::auto_ptr<IOutputStream> output;
@ -37,8 +39,10 @@ void CClient::run(const CNetworkAddress& serverAddress)
CTimerThread timer(30.0); // FIXME -- timeout in member CTimerThread timer(30.0); // FIXME -- timeout in member
// create socket and attempt to connect to server // create socket and attempt to connect to server
log((CLOG_DEBUG "connecting to server"));
socket.reset(new CTCPSocket()); // FIXME -- use factory socket.reset(new CTCPSocket()); // FIXME -- use factory
socket->connect(serverAddress); socket->connect(serverAddress);
log((CLOG_INFO "connected to server"));
// get the input and output streams // get the input and output streams
IInputStream* srcInput = socket->getInputStream(); IInputStream* srcInput = socket->getInputStream();
@ -59,16 +63,19 @@ void CClient::run(const CNetworkAddress& serverAddress)
output.reset(new COutputPacketStream(srcOutput, true)); output.reset(new COutputPacketStream(srcOutput, true));
// wait for hello from server // wait for hello from server
log((CLOG_DEBUG "wait for hello"));
SInt32 major, minor; SInt32 major, minor;
CProtocolUtil::readf(input.get(), "Synergy%2i%2i", &major, &minor); CProtocolUtil::readf(input.get(), "Synergy%2i%2i", &major, &minor);
// check versions // check versions
log((CLOG_DEBUG "got hello version %d.%d", major, minor));
if (major < kMajorVersion || if (major < kMajorVersion ||
(major == kMajorVersion && minor < kMinorVersion)) { (major == kMajorVersion && minor < kMinorVersion)) {
throw XIncompatibleClient(major, minor); throw XIncompatibleClient(major, minor);
} }
// say hello back // say hello back
log((CLOG_DEBUG "say hello version %d.%d", kMajorVersion, kMinorVersion));
CProtocolUtil::writef(output.get(), "Synergy%2i%2i%s", CProtocolUtil::writef(output.get(), "Synergy%2i%2i%s",
kMajorVersion, kMinorVersion, kMajorVersion, kMinorVersion,
m_name.size(), m_name.data()); m_name.size(), m_name.data());
@ -78,27 +85,27 @@ void CClient::run(const CNetworkAddress& serverAddress)
m_output = output.get(); m_output = output.get();
} }
catch (XIncompatibleClient& e) { catch (XIncompatibleClient& e) {
fprintf(stderr, "incompatible server version (%d.%d)\n", log((CLOG_ERR "server has incompatible version %d.%d", e.getMajor(), e.getMinor()));
e.getMajor(), e.getMinor());
return; return;
} }
catch (XThread&) { catch (XThread&) {
fprintf(stderr, "connection timed out\n"); log((CLOG_ERR "connection timed out"));
throw; throw;
} }
catch (XBase& e) { catch (XBase& e) {
fprintf(stderr, "connection failed: %s\n", e.what()); log((CLOG_ERR "connection failed: %s", e.what()));
return; return;
} }
// connect to screen // connect to screen
std::auto_ptr<CScreenCleaner> screenCleaner; std::auto_ptr<CScreenCleaner> screenCleaner;
try { try {
log((CLOG_DEBUG "creating secondary screen"));
m_screen = new CXWindowsSecondaryScreen; m_screen = new CXWindowsSecondaryScreen;
screenCleaner.reset(new CScreenCleaner(this, m_screen)); screenCleaner.reset(new CScreenCleaner(this, m_screen));
} }
catch (XBase& e) { catch (XBase& e) {
fprintf(stderr, "cannot open screen: %s\n", e.what()); log((CLOG_ERR "cannot open screen: %s", e.what()));
return; return;
} }
@ -106,21 +113,24 @@ void CClient::run(const CNetworkAddress& serverAddress)
// handle messages from server // handle messages from server
for (;;) { for (;;) {
// wait for reply // wait for reply
log((CLOG_DEBUG "waiting for message"));
UInt8 code[4]; UInt8 code[4];
UInt32 n = input->read(code, 4); UInt32 n = input->read(code, 4);
// verify we got an entire code // verify we got an entire code
if (n == 0) { if (n == 0) {
log((CLOG_NOTE "server disconnected"));
// server hungup // server hungup
break; break;
} }
if (n != 4) { if (n != 4) {
// client sent an incomplete message // client sent an incomplete message
fprintf(stderr, "incomplete message from server\n"); log((CLOG_ERR "incomplete message from server"));
break; break;
} }
// parse message // 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) { if (memcmp(code, kMsgDMouseMove, 4) == 0) {
onMouseMove(); onMouseMove();
} }
@ -169,20 +179,22 @@ void CClient::run(const CNetworkAddress& serverAddress)
} }
else { else {
// unknown message // unknown message
fprintf(stderr, "unknown message from server\n"); log((CLOG_ERR "unknown message from server"));
break; break;
} }
} }
} }
catch (XBase& e) { catch (XBase& e) {
fprintf(stderr, "error: %s\n", e.what()); log((CLOG_ERR "error: %s", e.what()));
return; return;
} }
// done with screen // done with screen
log((CLOG_DEBUG "destroying secondary screen"));
screenCleaner.reset(); screenCleaner.reset();
// done with socket // done with socket
log((CLOG_DEBUG "disconnecting from server"));
socket->close(); socket->close();
} }
@ -215,6 +227,7 @@ void CClient::onQueryInfo()
SInt32 w, h; SInt32 w, h;
m_screen->getSize(&w, &h); m_screen->getSize(&w, &h);
SInt32 zoneSize = m_screen->getJumpZoneSize(); 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); CProtocolUtil::writef(m_output, kMsgDInfo, w, h, zoneSize);
} }

View File

@ -87,3 +87,9 @@ CString CScreenMap::getNeighbor(const CString& srcName,
// return connection // return connection
return index->second.m_neighbor[srcSide - kFirstDirection]; 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];
}

View File

@ -33,6 +33,9 @@ class CScreenMap {
// if there is no neighbor in that direction. // if there is no neighbor in that direction.
CString getNeighbor(const CString&, EDirection) const throw(); CString getNeighbor(const CString&, EDirection) const throw();
// get the name of a direction (for debugging)
static const char* dirName(EDirection);
private: private:
class CCell { class CCell {
public: public:

View File

@ -16,7 +16,7 @@
#include "CTimerThread.h" #include "CTimerThread.h"
#include "CStopwatch.h" #include "CStopwatch.h"
#include "TMethodJob.h" #include "TMethodJob.h"
#include <stdio.h> #include "CLog.h"
#include <assert.h> #include <assert.h>
#include <memory> #include <memory>
@ -38,6 +38,8 @@ CServer::~CServer()
void CServer::run() void CServer::run()
{ {
try { try {
log((CLOG_NOTE "starting server"));
// connect to primary screen // connect to primary screen
openPrimaryScreen(); openPrimaryScreen();
@ -48,23 +50,27 @@ void CServer::run()
// FIXME // FIXME
// wait until done // wait until done
log((CLOG_DEBUG "waiting for quit"));
CLock lock(&m_mutex); CLock lock(&m_mutex);
while (m_done == false) { while (m_done == false) {
m_done.wait(); m_done.wait();
} }
// clean up // clean up
log((CLOG_DEBUG "stopping server"));
closePrimaryScreen(); closePrimaryScreen();
cleanupThreads(); cleanupThreads();
} }
catch (XBase& e) { catch (XBase& e) {
fprintf(stderr, "server error: %s\n", e.what()); log((CLOG_ERR "server error: %s\n", e.what()));
// clean up // clean up
closePrimaryScreen(); closePrimaryScreen();
cleanupThreads(); cleanupThreads();
} }
catch (...) { catch (...) {
log((CLOG_DEBUG "server shutdown"));
// clean up // clean up
closePrimaryScreen(); closePrimaryScreen();
cleanupThreads(); cleanupThreads();
@ -108,6 +114,7 @@ void CServer::setInfo(const CString& client,
info->m_width = w; info->m_width = w;
info->m_height = h; info->m_height = h;
info->m_zoneSize = zoneSize; 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*/, bool CServer::onCommandKey(KeyID /*id*/,
@ -118,6 +125,7 @@ bool CServer::onCommandKey(KeyID /*id*/,
void CServer::onKeyDown(KeyID id, KeyModifierMask mask) void CServer::onKeyDown(KeyID id, KeyModifierMask mask)
{ {
log((CLOG_DEBUG "onKeyDown id=%d mask=0x%04x", id, mask));
assert(m_active != NULL); assert(m_active != NULL);
// handle command keys // handle command keys
@ -133,6 +141,7 @@ void CServer::onKeyDown(KeyID id, KeyModifierMask mask)
void CServer::onKeyUp(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); assert(m_active != NULL);
// handle command keys // handle command keys
@ -148,6 +157,7 @@ void CServer::onKeyUp(KeyID id, KeyModifierMask mask)
void CServer::onKeyRepeat(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); assert(m_active != NULL);
// handle command keys // handle command keys
@ -164,6 +174,7 @@ void CServer::onKeyRepeat(KeyID id, KeyModifierMask mask)
void CServer::onMouseDown(ButtonID id) void CServer::onMouseDown(ButtonID id)
{ {
log((CLOG_DEBUG "onMouseDown id=%d", id));
assert(m_active != NULL); assert(m_active != NULL);
// relay // relay
@ -174,6 +185,7 @@ void CServer::onMouseDown(ButtonID id)
void CServer::onMouseUp(ButtonID id) void CServer::onMouseUp(ButtonID id)
{ {
log((CLOG_DEBUG "onMouseUp id=%d", id));
assert(m_active != NULL); assert(m_active != NULL);
// relay // relay
@ -184,6 +196,8 @@ void CServer::onMouseUp(ButtonID id)
void CServer::onMouseMovePrimary(SInt32 x, SInt32 y) void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
{ {
log((CLOG_DEBUG "onMouseMovePrimary %d,%d", x, y));
// mouse move on primary (server's) screen // mouse move on primary (server's) screen
assert(m_active != NULL); assert(m_active != NULL);
assert(m_active->m_protocol == NULL); assert(m_active->m_protocol == NULL);
@ -198,18 +212,22 @@ void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
if (x < m_active->m_zoneSize) { if (x < m_active->m_zoneSize) {
x -= m_active->m_zoneSize; x -= m_active->m_zoneSize;
dir = CScreenMap::kLeft; dir = CScreenMap::kLeft;
log((CLOG_DEBUG "switch to left"));
} }
else if (x >= m_active->m_width - m_active->m_zoneSize) { else if (x >= m_active->m_width - m_active->m_zoneSize) {
x += m_active->m_zoneSize; x += m_active->m_zoneSize;
dir = CScreenMap::kRight; dir = CScreenMap::kRight;
log((CLOG_DEBUG "switch to right"));
} }
else if (y < m_active->m_zoneSize) { else if (y < m_active->m_zoneSize) {
y -= m_active->m_zoneSize; y -= m_active->m_zoneSize;
dir = CScreenMap::kTop; dir = CScreenMap::kTop;
log((CLOG_DEBUG "switch to top"));
} }
else if (y >= m_active->m_height - m_active->m_zoneSize) { else if (y >= m_active->m_height - m_active->m_zoneSize) {
y += m_active->m_zoneSize; y += m_active->m_zoneSize;
dir = CScreenMap::kBottom; dir = CScreenMap::kBottom;
log((CLOG_DEBUG "switch to bottom"));
} }
else { else {
// still on local screen // still on local screen
@ -233,6 +251,8 @@ void CServer::onMouseMovePrimary(SInt32 x, SInt32 y)
void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy) void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
{ {
log((CLOG_DEBUG "onMouseMoveSecondary %+d,%+d", dx, dy));
// mouse move on secondary (client's) screen // mouse move on secondary (client's) screen
assert(m_active != NULL); assert(m_active != NULL);
assert(m_active->m_protocol != NULL); assert(m_active->m_protocol != NULL);
@ -264,8 +284,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
// get neighbor if we should switch // get neighbor if we should switch
if (newScreen == NULL) { if (newScreen == NULL) {
// TRACE(("leave %s on %s", m_activeScreen->getName().c_str(), log((CLOG_DEBUG "leave \"%s\" on %s", m_active->m_name.c_str(), CScreenMap::dirName(dir)));
// s_dirName[dir]));
SInt32 x = m_x, y = m_y; SInt32 x = m_x, y = m_y;
newScreen = getNeighbor(m_active, dir, x, y); newScreen = getNeighbor(m_active, dir, x, y);
@ -290,7 +309,7 @@ void CServer::onMouseMoveSecondary(SInt32 dx, SInt32 dy)
} }
else { else {
// clamp to edge when locked // 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) if (m_x < 0)
m_x = 0; m_x = 0;
else if (m_x > m_active->m_width - 1) 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) { if (newScreen == NULL || newScreen == m_active) {
// do nothing if mouse didn't move // do nothing if mouse didn't move
if (m_x != xOld || m_y != yOld) { if (m_x != xOld || m_y != yOld) {
// TRACE(("move on %s to %d,%d", log((CLOG_DEBUG "move on %s to %d,%d", m_active->m_name.c_str(), m_x, m_y));
// m_activeScreen->getName().c_str(), m_x, m_y));
m_active->m_protocol->sendMouseMove(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) void CServer::onMouseWheel(SInt32 delta)
{ {
log((CLOG_DEBUG "onMouseWheel %+d", delta));
assert(m_active != NULL); assert(m_active != NULL);
// relay // relay
@ -340,8 +359,7 @@ void CServer::switchScreen(CScreenInfo* dst,
assert(x >= 0 && y >= 0 && x < dst->m_width && y < dst->m_height); assert(x >= 0 && y >= 0 && x < dst->m_width && y < dst->m_height);
assert(m_active != NULL); assert(m_active != NULL);
// TRACE(("switch %s to %s at %d,%d", m_active->m_name.c_str(), log((CLOG_NOTE "switch from \"%s\" to \"%s\" at %d,%d", m_active->m_name.c_str(), dst->m_name.c_str(), x, y));
// dst->m_name.c_str(), x, y));
// wrapping means leaving the active screen and entering it again. // wrapping means leaving the active screen and entering it again.
// since that's a waste of time we skip that and just warp the // 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; CString srcName = src->m_name;
assert(!srcName.empty()); assert(!srcName.empty());
log((CLOG_DEBUG "find neighbor on %s of \"%s\"", CScreenMap::dirName(dir), srcName.c_str()));
for (;;) { for (;;) {
// look up name of neighbor // look up name of neighbor
const CString dstName(m_screenMap.getNeighbor(srcName, dir)); const CString dstName(m_screenMap.getNeighbor(srcName, dir));
// if nothing in that direction then return NULL // 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; return NULL;
}
// look up neighbor cell. if the screen is connected then // look up neighbor cell. if the screen is connected then
// we can stop. otherwise we skip over an unconnected // we can stop. otherwise we skip over an unconnected
// screen. // screen.
CScreenList::const_iterator index = m_screens.find(dstName); CScreenList::const_iterator index = m_screens.find(dstName);
if (index != m_screens.end()) { 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; return index->second;
} }
log((CLOG_DEBUG "ignored \"%s\" on %s of \"%s\"", dstName.c_str(), CScreenMap::dirName(dir), srcName.c_str()));
srcName = dstName; srcName = dstName;
} }
} }
@ -431,7 +454,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (x >= 0) { if (x >= 0) {
break; 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); dst = getNeighbor(lastGoodScreen, srcSide);
} }
break; break;
@ -445,7 +468,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (x < w) { if (x < w) {
break; 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); dst = getNeighbor(lastGoodScreen, srcSide);
} }
break; break;
@ -459,7 +482,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (y >= 0) { if (y >= 0) {
break; 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); dst = getNeighbor(lastGoodScreen, srcSide);
} }
break; break;
@ -473,7 +496,7 @@ CServer::CScreenInfo* CServer::getNeighbor(CScreenInfo* src,
if (y < h) { if (y < h) {
break; 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); dst = getNeighbor(lastGoodScreen, srcSide);
} }
break; break;
@ -548,6 +571,8 @@ void CServer::mapPosition(CScreenInfo* src,
#include "CTCPListenSocket.h" #include "CTCPListenSocket.h"
void CServer::acceptClients(void*) void CServer::acceptClients(void*)
{ {
log((CLOG_DEBUG "starting to wait for clients"));
// add this thread to the list of threads to cancel. remove from // add this thread to the list of threads to cancel. remove from
// list in d'tor. // list in d'tor.
CCleanupNote cleanupNote(this); CCleanupNote cleanupNote(this);
@ -564,25 +589,30 @@ void CServer::acceptClients(void*)
CNetworkAddress addr(50001 /* FIXME -- m_port */); CNetworkAddress addr(50001 /* FIXME -- m_port */);
for (;;) { for (;;) {
try { try {
log((CLOG_DEBUG "binding listen socket"));
listen->bind(addr); listen->bind(addr);
break; break;
} }
catch (XSocketAddressInUse&) { catch (XSocketAddressInUse&) {
// give up if we've waited too long // give up if we've waited too long
if (timer.getTime() >= m_bindTimeout) { if (timer.getTime() >= m_bindTimeout) {
log((CLOG_DEBUG "waited too long to bind, giving up"));
throw; throw;
} }
// wait a bit before retrying // wait a bit before retrying
log((CLOG_DEBUG "bind failed; waiting to retry"));
CThread::sleep(5.0); CThread::sleep(5.0);
} }
} }
// accept connections and begin processing them // accept connections and begin processing them
log((CLOG_DEBUG "waiting for client connections"));
for (;;) { for (;;) {
// accept connection // accept connection
CThread::testCancel(); CThread::testCancel();
ISocket* socket = listen->accept(); ISocket* socket = listen->accept();
log((CLOG_NOTE "accepted client connection"));
CThread::testCancel(); CThread::testCancel();
// start handshake thread // start handshake thread
@ -591,13 +621,15 @@ void CServer::acceptClients(void*)
} }
} }
catch (XBase& e) { catch (XBase& e) {
fprintf(stderr, "cannot listen for clients: %s\n", e.what()); log((CLOG_ERR "cannot listen for clients: %s", e.what()));
quit(); quit();
} }
} }
void CServer::handshakeClient(void* vsocket) void CServer::handshakeClient(void* vsocket)
{ {
log((CLOG_DEBUG "negotiating with new client"));
// get the socket pointer from the argument // get the socket pointer from the argument
assert(vsocket != NULL); assert(vsocket != NULL);
std::auto_ptr<ISocket> socket(reinterpret_cast<ISocket*>(vsocket)); std::auto_ptr<ISocket> socket(reinterpret_cast<ISocket*>(vsocket));
@ -638,11 +670,13 @@ void CServer::handshakeClient(void* vsocket)
static const UInt32 maxHelloLen = 1024; static const UInt32 maxHelloLen = 1024;
// say hello // say hello
log((CLOG_DEBUG "saying hello"));
CProtocolUtil::writef(output.get(), "Synergy%2i%2i", CProtocolUtil::writef(output.get(), "Synergy%2i%2i",
kMajorVersion, kMinorVersion); kMajorVersion, kMinorVersion);
output->flush(); output->flush();
// wait for the reply // wait for the reply
log((CLOG_DEBUG "waiting for hello reply"));
UInt32 n = input->getSize(); UInt32 n = input->getSize();
if (n > maxHelloLen) { if (n > maxHelloLen) {
throw XBadClient(); throw XBadClient();
@ -651,6 +685,7 @@ void CServer::handshakeClient(void* vsocket)
// get and parse the reply to hello // get and parse the reply to hello
SInt32 major, minor; SInt32 major, minor;
try { try {
log((CLOG_DEBUG "parsing hello reply"));
CProtocolUtil::readf(input.get(), "Synergy%2i%2i%s", CProtocolUtil::readf(input.get(), "Synergy%2i%2i%s",
&major, &minor, &name); &major, &minor, &name);
} }
@ -662,6 +697,7 @@ void CServer::handshakeClient(void* vsocket)
} }
// create a protocol interpreter for the version // 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, protocol.reset(CServerProtocol::create(major, minor,
this, name, input.get(), output.get())); this, name, input.get(), output.get()));
@ -670,28 +706,28 @@ void CServer::handshakeClient(void* vsocket)
name, protocol.get())); name, protocol.get()));
// ask and wait for the client's info // ask and wait for the client's info
log((CLOG_DEBUG "waiting for info for client %s", name.c_str()));
protocol->queryInfo(); protocol->queryInfo();
} }
// handle messages from client. returns when the client // handle messages from client. returns when the client
// disconnects. // disconnects.
log((CLOG_NOTE "client %s is connected", name.c_str()));
protocol->run(); protocol->run();
} }
catch (XIncompatibleClient& e) { catch (XIncompatibleClient& e) {
// client is incompatible // client is incompatible
fprintf(stderr, "client is incompatible (%s, %d.%d)\n", log((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
name.c_str(), e.getMajor(), e.getMinor());
// FIXME -- could print network address if socket had suitable method // FIXME -- could print network address if socket had suitable method
} }
catch (XBadClient&) { catch (XBadClient&) {
// client not behaving // 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 // FIXME -- could print network address if socket had suitable method
} }
catch (XBase& e) { catch (XBase& e) {
// misc error // misc error
fprintf(stderr, "error communicating with client %s: %s\n", log((CLOG_WARN "error communicating with client \"%s\": %s", name.c_str(), e.what()));
name.c_str(), e.what());
// FIXME -- could print network address if socket had suitable method // FIXME -- could print network address if socket had suitable method
} }
} }
@ -710,7 +746,9 @@ void CServer::openPrimaryScreen()
assert(m_primary == NULL); assert(m_primary == NULL);
// open screen // open screen
log((CLOG_DEBUG "creating primary screen"));
m_primary = new CXWindowsPrimaryScreen; m_primary = new CXWindowsPrimaryScreen;
log((CLOG_DEBUG "opening primary screen"));
m_primary->open(this); m_primary->open(this);
// add connection // add connection
@ -719,6 +757,7 @@ void CServer::openPrimaryScreen()
// update info // update info
m_primary->getSize(&m_active->m_width, &m_active->m_height); m_primary->getSize(&m_active->m_width, &m_active->m_height);
m_active->m_zoneSize = m_primary->getJumpZoneSize(); 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 // FIXME -- need way for primary screen to call us back
} }
@ -731,6 +770,7 @@ void CServer::closePrimaryScreen() throw()
// close the primary screen // close the primary screen
try { try {
log((CLOG_DEBUG "closing primary screen"));
m_primary->close(); m_primary->close();
} }
catch (...) { catch (...) {
@ -738,6 +778,7 @@ void CServer::closePrimaryScreen() throw()
} }
// clean up // clean up
log((CLOG_DEBUG "destroying primary screen"));
delete m_primary; delete m_primary;
m_primary = NULL; m_primary = NULL;
} }
@ -763,6 +804,7 @@ void CServer::removeCleanupThread(const CThread& thread)
void CServer::cleanupThreads() throw() void CServer::cleanupThreads() throw()
{ {
log((CLOG_DEBUG "cleaning up threads"));
m_mutex.lock(); m_mutex.lock();
while (m_cleanupList.begin() != m_cleanupList.end()) { while (m_cleanupList.begin() != m_cleanupList.end()) {
// get the next thread and cancel it // get the next thread and cancel it
@ -778,11 +820,13 @@ void CServer::cleanupThreads() throw()
// FIXME -- delete remaining threads from list // FIXME -- delete remaining threads from list
m_mutex.unlock(); m_mutex.unlock();
log((CLOG_DEBUG "cleaned up threads"));
} }
CServer::CScreenInfo* CServer::addConnection( CServer::CScreenInfo* CServer::addConnection(
const CString& name, IServerProtocol* protocol) const CString& name, IServerProtocol* protocol)
{ {
log((CLOG_DEBUG "adding connection \"%s\"", name.c_str()));
CLock lock(&m_mutex); CLock lock(&m_mutex);
assert(m_screens.count(name) == 0); assert(m_screens.count(name) == 0);
CScreenInfo* newScreen = new CScreenInfo(name, protocol); CScreenInfo* newScreen = new CScreenInfo(name, protocol);
@ -792,6 +836,7 @@ CServer::CScreenInfo* CServer::addConnection(
void CServer::removeConnection(const CString& name) void CServer::removeConnection(const CString& name)
{ {
log((CLOG_DEBUG "removing connection \"%s\"", name.c_str()));
CLock lock(&m_mutex); CLock lock(&m_mutex);
CScreenList::iterator index = m_screens.find(name); CScreenList::iterator index = m_screens.find(name);
assert(index == m_screens.end()); assert(index == m_screens.end());

View File

@ -3,6 +3,7 @@
#include "CProtocolUtil.h" #include "CProtocolUtil.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "IInputStream.h" #include "IInputStream.h"
#include "CLog.h"
#include <string.h> #include <string.h>
// //
@ -40,6 +41,7 @@ void CServerProtocol1_0::run() throw(XIO,XBadClient)
} }
// parse message // 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) { if (memcmp(code, kMsgDInfo, 4) == 0) {
recvInfo(); recvInfo();
} }
@ -53,6 +55,8 @@ void CServerProtocol1_0::run() throw(XIO,XBadClient)
void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient) void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient)
{ {
log((CLOG_INFO "querying client \"%s\" info", getClient().c_str()));
// send request // send request
CProtocolUtil::writef(getOutputStream(), kMsgQInfo); CProtocolUtil::writef(getOutputStream(), kMsgQInfo);
@ -69,74 +73,87 @@ void CServerProtocol1_0::queryInfo() throw(XIO,XBadClient)
void CServerProtocol1_0::sendClose() throw(XIO) void CServerProtocol1_0::sendClose() throw(XIO)
{ {
log((CLOG_INFO "send close to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCClose); CProtocolUtil::writef(getOutputStream(), kMsgCClose);
} }
void CServerProtocol1_0::sendEnter( void CServerProtocol1_0::sendEnter(
SInt32 xAbs, SInt32 yAbs) throw(XIO) 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); CProtocolUtil::writef(getOutputStream(), kMsgCEnter, xAbs, yAbs);
} }
void CServerProtocol1_0::sendLeave() throw(XIO) void CServerProtocol1_0::sendLeave() throw(XIO)
{ {
log((CLOG_INFO "send leave to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCLeave); CProtocolUtil::writef(getOutputStream(), kMsgCLeave);
} }
void CServerProtocol1_0::sendGrabClipboard() throw(XIO) void CServerProtocol1_0::sendGrabClipboard() throw(XIO)
{ {
log((CLOG_INFO "send grab clipboard to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgCClipboard); CProtocolUtil::writef(getOutputStream(), kMsgCClipboard);
} }
void CServerProtocol1_0::sendQueryClipboard() throw(XIO) void CServerProtocol1_0::sendQueryClipboard() throw(XIO)
{ {
log((CLOG_INFO "query clipboard to \"%s\"", getClient().c_str()));
CProtocolUtil::writef(getOutputStream(), kMsgQClipboard); CProtocolUtil::writef(getOutputStream(), kMsgQClipboard);
} }
void CServerProtocol1_0::sendScreenSaver(bool on) throw(XIO) 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); CProtocolUtil::writef(getOutputStream(), kMsgCScreenSaver, on ? 1 : 0);
} }
void CServerProtocol1_0::sendKeyDown( void CServerProtocol1_0::sendKeyDown(
KeyID key, KeyModifierMask mask) throw(XIO) 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); CProtocolUtil::writef(getOutputStream(), kMsgDKeyDown, key, mask);
} }
void CServerProtocol1_0::sendKeyRepeat( void CServerProtocol1_0::sendKeyRepeat(
KeyID key, KeyModifierMask mask) throw(XIO) 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); CProtocolUtil::writef(getOutputStream(), kMsgDKeyRepeat, key, mask);
} }
void CServerProtocol1_0::sendKeyUp( void CServerProtocol1_0::sendKeyUp(
KeyID key, KeyModifierMask mask) throw(XIO) 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); CProtocolUtil::writef(getOutputStream(), kMsgDKeyUp, key, mask);
} }
void CServerProtocol1_0::sendMouseDown( void CServerProtocol1_0::sendMouseDown(
ButtonID button) throw(XIO) ButtonID button) throw(XIO)
{ {
log((CLOG_INFO "send mouse down to \"%s\" id=%d", getClient().c_str(), button));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseDown, button); CProtocolUtil::writef(getOutputStream(), kMsgDMouseDown, button);
} }
void CServerProtocol1_0::sendMouseUp( void CServerProtocol1_0::sendMouseUp(
ButtonID button) throw(XIO) ButtonID button) throw(XIO)
{ {
log((CLOG_INFO "send mouse up to \"%s\" id=%d", getClient().c_str(), button));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseUp, button); CProtocolUtil::writef(getOutputStream(), kMsgDMouseUp, button);
} }
void CServerProtocol1_0::sendMouseMove( void CServerProtocol1_0::sendMouseMove(
SInt32 xAbs, SInt32 yAbs) throw(XIO) 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); CProtocolUtil::writef(getOutputStream(), kMsgDMouseMove, xAbs, yAbs);
} }
void CServerProtocol1_0::sendMouseWheel( void CServerProtocol1_0::sendMouseWheel(
SInt32 delta) throw(XIO) SInt32 delta) throw(XIO)
{ {
log((CLOG_INFO "send mouse wheel to \"%s\" %+d", getClient().c_str(), delta));
CProtocolUtil::writef(getOutputStream(), kMsgDMouseWheel, delta); CProtocolUtil::writef(getOutputStream(), kMsgDMouseWheel, delta);
} }
@ -145,6 +162,7 @@ void CServerProtocol1_0::recvInfo() throw(XIO,XBadClient)
// parse the message // parse the message
SInt32 w, h, zoneInfo; SInt32 w, h, zoneInfo;
CProtocolUtil::readf(getInputStream(), kMsgDInfo + 4, &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 // validate
if (w == 0 || h == 0) { if (w == 0 || h == 0) {

View File

@ -2,6 +2,7 @@
#include "CServer.h" #include "CServer.h"
#include "CThread.h" #include "CThread.h"
#include "TMethodJob.h" #include "TMethodJob.h"
#include "CLog.h"
#include <assert.h> #include <assert.h>
#include <X11/X.h> #include <X11/X.h>
@ -33,6 +34,7 @@ void CXWindowsPrimaryScreen::open(CServer* server)
m_server = server; m_server = server;
// open the display // open the display
log((CLOG_DEBUG "XOpenDisplay(%s)", "NULL"));
m_display = ::XOpenDisplay(NULL); // FIXME -- allow non-default m_display = ::XOpenDisplay(NULL); // FIXME -- allow non-default
if (m_display == NULL) if (m_display == NULL)
throw int(5); // FIXME -- make exception for this throw int(5); // FIXME -- make exception for this
@ -44,6 +46,7 @@ void CXWindowsPrimaryScreen::open(CServer* server)
// get screen size // get screen size
m_w = WidthOfScreen(screen); m_w = WidthOfScreen(screen);
m_h = HeightOfScreen(screen); m_h = HeightOfScreen(screen);
log((CLOG_INFO "primary display size: %dx%d", m_w, m_h));
// get the root window // get the root window
Window root = RootWindow(m_display, m_screen); Window root = RootWindow(m_display, m_screen);
@ -80,10 +83,12 @@ void CXWindowsPrimaryScreen::close()
assert(m_eventThread != NULL); assert(m_eventThread != NULL);
// stop event thread // stop event thread
log((CLOG_DEBUG "stopping event thread"));
m_eventThread->cancel(); m_eventThread->cancel();
m_eventThread->wait(); m_eventThread->wait();
delete m_eventThread; delete m_eventThread;
m_eventThread = NULL; m_eventThread = NULL;
log((CLOG_DEBUG "stopped event thread"));
// destroy window // destroy window
::XDestroyWindow(m_display, m_window); ::XDestroyWindow(m_display, m_window);
@ -92,10 +97,12 @@ void CXWindowsPrimaryScreen::close()
// close the display // close the display
::XCloseDisplay(m_display); ::XCloseDisplay(m_display);
m_display = NULL; m_display = NULL;
log((CLOG_DEBUG "closed display"));
} }
void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y) void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y)
{ {
log((CLOG_INFO "entering primary at %d,%d", x, y));
assert(m_display != NULL); assert(m_display != NULL);
assert(m_window != None); assert(m_window != None);
assert(m_active == true); assert(m_active == true);
@ -123,6 +130,7 @@ void CXWindowsPrimaryScreen::enter(SInt32 x, SInt32 y)
void CXWindowsPrimaryScreen::leave() void CXWindowsPrimaryScreen::leave()
{ {
log((CLOG_INFO "leaving primary"));
assert(m_display != NULL); assert(m_display != NULL);
assert(m_window != None); assert(m_window != None);
assert(m_active == false); assert(m_active == false);
@ -141,9 +149,12 @@ void CXWindowsPrimaryScreen::leave()
GrabModeAsync, GrabModeAsync, GrabModeAsync, GrabModeAsync,
m_window, None, CurrentTime); m_window, None, CurrentTime);
assert(result != GrabNotViewable); assert(result != GrabNotViewable);
if (result != GrabSuccess) if (result != GrabSuccess) {
log((CLOG_DEBUG "waiting to grab pointer"));
CThread::sleep(0.25); CThread::sleep(0.25);
}
} while (result != GrabSuccess); } while (result != GrabSuccess);
log((CLOG_DEBUG "grabbed pointer"));
// now the keyboard // now the keyboard
result = ::XGrabKeyboard(m_display, m_window, True, result = ::XGrabKeyboard(m_display, m_window, True,
@ -151,9 +162,11 @@ void CXWindowsPrimaryScreen::leave()
assert(result != GrabNotViewable); assert(result != GrabNotViewable);
if (result != GrabSuccess) { if (result != GrabSuccess) {
::XUngrabPointer(m_display, CurrentTime); ::XUngrabPointer(m_display, CurrentTime);
log((CLOG_DEBUG "ungrabbed pointer, waiting to grab keyboard"));
CThread::sleep(0.25); CThread::sleep(0.25);
} }
} while (result != GrabSuccess); } while (result != GrabSuccess);
log((CLOG_DEBUG "grabbed keyboard"));
// move the mouse to the center of grab window // move the mouse to the center of grab window
warpCursor(m_w >> 1, m_h >> 1); 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); Window root = RootWindow(m_display, m_screen);
::XWarpPointer(m_display, None, root, 0, 0, 0, 0, x, y); ::XWarpPointer(m_display, None, root, 0, 0, 0, 0, x, y);
::XSync(m_display, False); ::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 // discard mouse events since we just added one we don't want
XEvent xevent; XEvent xevent;
@ -237,6 +251,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
break; break;
case KeyPress: { 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 KeyModifierMask mask = mapModifier(xevent.xkey.state);
const KeyID key = mapKey(xevent.xkey.keycode, mask); const KeyID key = mapKey(xevent.xkey.keycode, mask);
if (key != kKeyNone) { if (key != kKeyNone) {
@ -248,6 +263,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
// FIXME -- simulate key repeat. X sends press/release for // FIXME -- simulate key repeat. X sends press/release for
// repeat. must detect auto repeat and use kKeyRepeat. // repeat. must detect auto repeat and use kKeyRepeat.
case KeyRelease: { 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 KeyModifierMask mask = mapModifier(xevent.xkey.state);
const KeyID key = mapKey(xevent.xkey.keycode, mask); const KeyID key = mapKey(xevent.xkey.keycode, mask);
if (key != kKeyNone) { if (key != kKeyNone) {
@ -257,6 +273,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
} }
case ButtonPress: { case ButtonPress: {
log((CLOG_DEBUG "event: ButtonPress button=%d", xevent.xbutton.button));
const ButtonID button = mapButton(xevent.xbutton.button); const ButtonID button = mapButton(xevent.xbutton.button);
if (button != kButtonNone) { if (button != kButtonNone) {
m_server->onMouseDown(button); m_server->onMouseDown(button);
@ -265,6 +282,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
} }
case ButtonRelease: { case ButtonRelease: {
log((CLOG_DEBUG "event: ButtonRelease button=%d", xevent.xbutton.button));
const ButtonID button = mapButton(xevent.xbutton.button); const ButtonID button = mapButton(xevent.xbutton.button);
if (button != kButtonNone) { if (button != kButtonNone) {
m_server->onMouseUp(button); m_server->onMouseUp(button);
@ -273,6 +291,7 @@ void CXWindowsPrimaryScreen::eventThread(void*)
} }
case MotionNotify: { case MotionNotify: {
log((CLOG_DEBUG "event: MotionNotify %d,%d", xevent.xmotion.x_root, xevent.xmotion.y_root));
SInt32 x, y; SInt32 x, y;
if (!m_active) { if (!m_active) {
x = xevent.xmotion.x_root; x = xevent.xmotion.x_root;