now using class factories to move some decisions from the libraries

into the application.
This commit is contained in:
crs 2002-07-30 18:31:00 +00:00
parent fee4095624
commit 69496abbab
20 changed files with 370 additions and 84 deletions

View File

@ -1,9 +1,11 @@
#include "CClient.h" #include "CClient.h"
#include "ISecondaryScreenFactory.h"
#include "CPlatform.h" #include "CPlatform.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "Version.h" #include "Version.h"
#include "CNetwork.h" #include "CNetwork.h"
#include "CNetworkAddress.h" #include "CNetworkAddress.h"
#include "CTCPSocketFactory.h"
#include "XSocket.h" #include "XSocket.h"
#include "CCondVar.h" #include "CCondVar.h"
#include "CLock.h" #include "CLock.h"
@ -14,6 +16,12 @@
#include "CString.h" #include "CString.h"
#include <cstring> #include <cstring>
#if WINDOWS_LIKE
#include "CMSWindowsSecondaryScreen.h"
#elif UNIX_LIKE
#include "CXWindowsSecondaryScreen.h"
#endif
// platform dependent name of a daemon // platform dependent name of a daemon
#if WINDOWS_LIKE #if WINDOWS_LIKE
#define DAEMON_NAME "Synergy Client" #define DAEMON_NAME "Synergy Client"
@ -57,6 +65,31 @@ logLock(bool lock)
} }
//
// platform dependent factories
//
class CSecondaryScreenFactory : public ISecondaryScreenFactory {
public:
CSecondaryScreenFactory() { }
virtual ~CSecondaryScreenFactory() { }
// ISecondaryScreenFactory overrides
virtual CSecondaryScreen*
create(IScreenReceiver*);
};
CSecondaryScreen*
CSecondaryScreenFactory::create(IScreenReceiver* receiver)
{
#if WINDOWS_LIKE
return new CMSWindowsSecondaryScreen(receiver);
#elif UNIX_LIKE
return new CXWindowsSecondaryScreen(receiver);
#endif
}
// //
// platform independent main // platform independent main
// //
@ -87,6 +120,11 @@ realMain(CMutex* mutex)
s_client = new CClient(s_name); s_client = new CClient(s_name);
s_client->camp(s_camp); s_client->camp(s_camp);
s_client->setAddress(s_serverAddress); s_client->setAddress(s_serverAddress);
s_client->setScreenFactory(new CSecondaryScreenFactory);
s_client->setSocketFactory(new CTCPSocketFactory);
s_client->setStreamFilterFactory(NULL);
// open client
if (s_client->open()) { if (s_client->open()) {
opened = true; opened = true;

View File

@ -1,9 +1,11 @@
#include "CServer.h" #include "CServer.h"
#include "CConfig.h" #include "CConfig.h"
#include "IPrimaryScreenFactory.h"
#include "CPlatform.h" #include "CPlatform.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "Version.h" #include "Version.h"
#include "CNetwork.h" #include "CNetwork.h"
#include "CTCPSocketFactory.h"
#include "XSocket.h" #include "XSocket.h"
#include "CLock.h" #include "CLock.h"
#include "CMutex.h" #include "CMutex.h"
@ -13,6 +15,12 @@
#include "stdfstream.h" #include "stdfstream.h"
#include <cstring> #include <cstring>
#if WINDOWS_LIKE
#include "CMSWindowsPrimaryScreen.h"
#elif UNIX_LIKE
#include "CXWindowsPrimaryScreen.h"
#endif
// platform dependent name of a daemon // platform dependent name of a daemon
#if WINDOWS_LIKE #if WINDOWS_LIKE
#define DAEMON_NAME "Synergy Server" #define DAEMON_NAME "Synergy Server"
@ -67,6 +75,32 @@ logLock(bool lock)
} }
//
// platform dependent factories
//
class CPrimaryScreenFactory : public IPrimaryScreenFactory {
public:
CPrimaryScreenFactory() { }
virtual ~CPrimaryScreenFactory() { }
// IPrimaryScreenFactory overrides
virtual CPrimaryScreen*
create(IScreenReceiver*, IPrimaryScreenReceiver*);
};
CPrimaryScreen*
CPrimaryScreenFactory::create(IScreenReceiver* receiver,
IPrimaryScreenReceiver* primaryReceiver)
{
#if WINDOWS_LIKE
return new CMSWindowsPrimaryScreen(receiver, primaryReceiver);
#elif UNIX_LIKE
return new CXWindowsPrimaryScreen(receiver, primaryReceiver);
#endif
}
// //
// platform independent main // platform independent main
// //
@ -117,6 +151,11 @@ realMain(CMutex* mutex)
// create server // create server
s_server = new CServer(s_name); s_server = new CServer(s_name);
s_server->setConfig(s_config); s_server->setConfig(s_config);
s_server->setScreenFactory(new CPrimaryScreenFactory);
s_server->setSocketFactory(new CTCPSocketFactory);
s_server->setStreamFilterFactory(NULL);
// open server
if (s_server->open()) { if (s_server->open()) {
opened = true; opened = true;

View File

@ -1,5 +1,6 @@
#include "CClient.h" #include "CClient.h"
#include "CServerProxy.h" #include "CServerProxy.h"
#include "ISecondaryScreenFactory.h"
#include "CClipboard.h" #include "CClipboard.h"
#include "CInputPacketStream.h" #include "CInputPacketStream.h"
#include "COutputPacketStream.h" #include "COutputPacketStream.h"
@ -9,7 +10,10 @@
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "XScreen.h" #include "XScreen.h"
#include "XSynergy.h" #include "XSynergy.h"
#include "IDataSocket.h"
#include "ISocketFactory.h"
#include "XSocket.h" #include "XSocket.h"
#include "IStreamFilterFactory.h"
#include "CLock.h" #include "CLock.h"
#include "CThread.h" #include "CThread.h"
#include "CTimerThread.h" #include "CTimerThread.h"
@ -27,6 +31,9 @@ CClient::CClient(const CString& clientName) :
m_screen(NULL), m_screen(NULL),
m_server(NULL), m_server(NULL),
m_camp(false), m_camp(false),
m_screenFactory(NULL),
m_socketFactory(NULL),
m_streamFilterFactory(NULL),
m_session(NULL), m_session(NULL),
m_active(false), m_active(false),
m_rejected(true) m_rejected(true)
@ -36,7 +43,9 @@ CClient::CClient(const CString& clientName) :
CClient::~CClient() CClient::~CClient()
{ {
// do nothing delete m_screenFactory;
delete m_socketFactory;
delete m_streamFilterFactory;
} }
void void
@ -53,6 +62,30 @@ CClient::setAddress(const CNetworkAddress& serverAddress)
m_serverAddress = serverAddress; m_serverAddress = serverAddress;
} }
void
CClient::setScreenFactory(ISecondaryScreenFactory* adopted)
{
CLock lock(&m_mutex);
delete m_screenFactory;
m_screenFactory = adopted;
}
void
CClient::setSocketFactory(ISocketFactory* adopted)
{
CLock lock(&m_mutex);
delete m_socketFactory;
m_socketFactory = adopted;
}
void
CClient::setStreamFilterFactory(IStreamFilterFactory* adopted)
{
CLock lock(&m_mutex);
delete m_streamFilterFactory;
m_streamFilterFactory = adopted;
}
void void
CClient::exitMainLoop() CClient::exitMainLoop()
{ {
@ -331,16 +364,11 @@ CClient::getCursorCenter(SInt32&, SInt32&) const
assert(0 && "shouldn't be called"); assert(0 && "shouldn't be called");
} }
// FIXME -- use factory to create screen
#if WINDOWS_LIKE
#include "CMSWindowsSecondaryScreen.h"
#elif UNIX_LIKE
#include "CXWindowsSecondaryScreen.h"
#endif
void void
CClient::openSecondaryScreen() CClient::openSecondaryScreen()
{ {
assert(m_screen == NULL); assert(m_screen == NULL);
assert(m_screenFactory != NULL);
// not active // not active
m_active = false; m_active = false;
@ -351,15 +379,16 @@ CClient::openSecondaryScreen()
m_timeClipboard[id] = 0; m_timeClipboard[id] = 0;
} }
// open screen // create screen
log((CLOG_DEBUG1 "creating secondary screen")); log((CLOG_DEBUG1 "creating secondary screen"));
#if WINDOWS_LIKE m_screen = m_screenFactory->create(this);
m_screen = new CMSWindowsSecondaryScreen(this); if (m_screen == NULL) {
#elif UNIX_LIKE throw XScreenOpenFailure();
m_screen = new CXWindowsSecondaryScreen(this); }
#endif
log((CLOG_DEBUG1 "opening secondary screen")); // open screen
try { try {
log((CLOG_DEBUG1 "opening secondary screen"));
m_screen->open(); m_screen->open();
} }
catch (...) { catch (...) {
@ -459,7 +488,6 @@ CClient::deleteSession(double timeout)
} }
} }
#include "CTCPSocket.h" // FIXME
void void
CClient::runServer() CClient::runServer()
{ {
@ -469,12 +497,14 @@ CClient::runServer()
for (;;) { for (;;) {
try { try {
// allow connect this much time to succeed // allow connect this much time to succeed
// FIXME -- timeout in member
CTimerThread timer(m_camp ? -1.0 : 30.0); CTimerThread timer(m_camp ? -1.0 : 30.0);
// create socket and attempt to connect to server // create socket and attempt to connect to server
log((CLOG_DEBUG1 "connecting to server")); log((CLOG_DEBUG1 "connecting to server"));
socket = new CTCPSocket; // FIXME -- use factory if (m_socketFactory != NULL) {
socket = m_socketFactory->create();
}
assert(socket != NULL);
socket->connect(m_serverAddress); socket->connect(m_serverAddress);
log((CLOG_INFO "connected to server")); log((CLOG_INFO "connected to server"));
break; break;
@ -553,14 +583,12 @@ CClient::handshakeServer(IDataSocket* socket)
IOutputStream* output = socket->getOutputStream(); IOutputStream* output = socket->getOutputStream();
bool own = false; bool own = false;
// attach the encryption layer // attach filters
/* FIXME -- implement ISecurityFactory if (m_streamFilterFactory != NULL) {
if (m_securityFactory != NULL) { input = m_streamFilterFactory->createInput(input, own);
input = m_securityFactory->createInputFilter(input, own); output = m_streamFilterFactory->createOutput(output, own);
output = m_securityFactory->createOutputFilter(output, own);
own = true; own = true;
} }
*/
// attach the packetizing filters // attach the packetizing filters
input = new CInputPacketStream(input, own); input = new CInputPacketStream(input, own);
@ -575,7 +603,7 @@ CClient::handshakeServer(IDataSocket* socket)
// wait for hello from server // wait for hello from server
log((CLOG_DEBUG1 "wait for hello")); log((CLOG_DEBUG1 "wait for hello"));
SInt16 major, minor; SInt16 major, minor;
CProtocolUtil::readf(input, "Synergy%2i%2i", &major, &minor); CProtocolUtil::readf(input, kMsgHello, &major, &minor);
// check versions // check versions
log((CLOG_DEBUG1 "got hello version %d.%d", major, minor)); log((CLOG_DEBUG1 "got hello version %d.%d", major, minor));
@ -586,7 +614,7 @@ CClient::handshakeServer(IDataSocket* socket)
// say hello back // say hello back
log((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion)); log((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion));
CProtocolUtil::writef(output, "Synergy%2i%2i%s", CProtocolUtil::writef(output, kMsgHelloBack,
kProtocolMajorVersion, kProtocolMajorVersion,
kProtocolMinorVersion, &m_name); kProtocolMinorVersion, &m_name);

View File

@ -12,6 +12,9 @@ class CServerProxy;
class CThread; class CThread;
class IDataSocket; class IDataSocket;
class IScreenReceiver; class IScreenReceiver;
class ISecondaryScreenFactory;
class ISocketFactory;
class IStreamFilterFactory;
//! Synergy client //! Synergy client
/*! /*!
@ -44,6 +47,30 @@ public:
*/ */
void setAddress(const CNetworkAddress& serverAddress); void setAddress(const CNetworkAddress& serverAddress);
//! Set secondary screen factory
/*!
Sets the factory for creating secondary screens. This must be
set before calling open(). This object takes ownership of the
factory.
*/
void setScreenFactory(ISecondaryScreenFactory*);
//! Set socket factory
/*!
Sets the factory used to create a socket to connect to the server.
This must be set before calling mainLoop(). This object takes
ownership of the factory.
*/
void setSocketFactory(ISocketFactory*);
//! Set stream filter factory
/*!
Sets the factory used to filter the socket streams used to
communicate with the server. This object takes ownership
of the factory.
*/
void setStreamFilterFactory(IStreamFilterFactory*);
//! Exit event loop //! Exit event loop
/*! /*!
Force mainLoop() to return. This call can return before Force mainLoop() to return. This call can return before
@ -117,6 +144,9 @@ private:
IScreenReceiver* m_server; IScreenReceiver* m_server;
CNetworkAddress m_serverAddress; CNetworkAddress m_serverAddress;
bool m_camp; bool m_camp;
ISecondaryScreenFactory* m_screenFactory;
ISocketFactory* m_socketFactory;
IStreamFilterFactory* m_streamFilterFactory;
CThread* m_session; CThread* m_session;
bool m_active; bool m_active;
bool m_rejected; bool m_rejected;

View File

@ -0,0 +1,24 @@
#ifndef ISECONDARYSCREENFACTORY_H
#define ISECONDARYSCREENFACTORY_H
#include "IInterface.h"
class CSecondaryScreen;
class IScreenReceiver;
//! Secondary screen factory interface
/*!
This interface provides factory methods to create secondary screens.
*/
class ISecondaryScreenFactory : public IInterface {
public:
//! Create screen
/*!
Create and return a secondary screen. The caller must delete the
returned object.
*/
virtual CSecondaryScreen*
create(IScreenReceiver*) = 0;
};
#endif

View File

@ -12,6 +12,7 @@ libclient_a_SOURCES = \
CSecondaryScreen.h \ CSecondaryScreen.h \
CServerProxy.h \ CServerProxy.h \
CXWindowsSecondaryScreen.h \ CXWindowsSecondaryScreen.h \
ISecondaryScreenFactory.h \
$(NULL) $(NULL)
INCLUDES = \ INCLUDES = \
-I$(DEPTH)/lib/base \ -I$(DEPTH)/lib/base \

View File

@ -0,0 +1,34 @@
#ifndef ISTREAMFILTERFACTORY_H
#define ISTREAMFILTERFACTORY_H
#include "IInterface.h"
class CInputStreamFilter;
class COutputStreamFilter;
class IInputStream;
class IOutputStream;
//! Stream filter factory interface
/*!
This interface provides factory methods to create stream filters.
*/
class IStreamFilterFactory : public IInterface {
public:
//! Create input filter
/*!
Create and return an input stream filter. The caller must delete the
returned object.
*/
virtual CInputStreamFilter*
createInput(IInputStream*, bool adoptStream) = 0;
//! Create output filter
/*!
Create and return an output stream filter. The caller must delete the
returned object.
*/
virtual COutputStreamFilter*
createOutput(IOutputStream*, bool adoptStream) = 0;
};
#endif

View File

@ -17,6 +17,7 @@ libio_a_SOURCES = \
CStreamBuffer.h \ CStreamBuffer.h \
IInputStream.h \ IInputStream.h \
IOutputStream.h \ IOutputStream.h \
IStreamFilterFactory.h \
XIO.h \ XIO.h \
$(NULL) $(NULL)
INCLUDES = \ INCLUDES = \

View File

@ -6,17 +6,20 @@ noinst_LIBRARIES = libnet.a
libnet_a_SOURCES = \ libnet_a_SOURCES = \
CNetwork.cpp \ CNetwork.cpp \
CNetworkAddress.cpp \ CNetworkAddress.cpp \
CTCPSocket.cpp \
CTCPListenSocket.cpp \ CTCPListenSocket.cpp \
CTCPSocket.cpp \
CTCPSocketFactory.cpp \
XNetwork.cpp \ XNetwork.cpp \
XSocket.cpp \ XSocket.cpp \
CNetwork.h \ CNetwork.h \
CNetworkAddress.h \ CNetworkAddress.h \
CTCPListenSocket.h \ CTCPListenSocket.h \
CTCPSocket.h \ CTCPSocket.h \
CTCPSocketFactory.h \
IDataSocket.h \ IDataSocket.h \
IListenSocket.h \ IListenSocket.h \
ISocket.h \ ISocket.h \
ISocketFactory.h \
XNetwork.h \ XNetwork.h \
XSocket.h \ XSocket.h \
$(NULL) $(NULL)

View File

@ -1,36 +1,29 @@
#include "CPrimaryClient.h" #include "CPrimaryClient.h"
#include "IPrimaryScreenFactory.h"
#include "IServer.h" #include "IServer.h"
#include "XSynergy.h" #include "XSynergy.h"
#include "CPrimaryScreen.h" #include "CPrimaryScreen.h"
#include "CClipboard.h" #include "CClipboard.h"
#include "CLog.h" #include "CLog.h"
// FIXME -- use factory to create screen
#if WINDOWS_LIKE
#include "CMSWindowsPrimaryScreen.h"
#elif UNIX_LIKE
#include "CXWindowsPrimaryScreen.h"
#endif
// //
// CPrimaryClient // CPrimaryClient
// //
CPrimaryClient::CPrimaryClient(IServer* server, CPrimaryClient::CPrimaryClient(IPrimaryScreenFactory* screenFactory,
IPrimaryScreenReceiver* receiver, const CString& name) : IServer* server,
IPrimaryScreenReceiver* receiver,
const CString& name) :
m_server(server), m_server(server),
m_name(name), m_name(name),
m_seqNum(0) m_seqNum(0)
{ {
assert(m_server != NULL); assert(m_server != NULL);
assert(screenFactory != NULL);
// create screen // create screen
log((CLOG_DEBUG1 "creating primary screen")); log((CLOG_DEBUG1 "creating primary screen"));
#if WINDOWS_LIKE m_screen = screenFactory->create(this, receiver);
m_screen = new CMSWindowsPrimaryScreen(this, receiver);
#elif UNIX_LIKE
m_screen = new CXWindowsPrimaryScreen(this, receiver);
#endif
} }
CPrimaryClient::~CPrimaryClient() CPrimaryClient::~CPrimaryClient()

View File

@ -7,6 +7,7 @@
class IClipboard; class IClipboard;
class CPrimaryScreen; class CPrimaryScreen;
class IPrimaryScreenFactory;
class IPrimaryScreenReceiver; class IPrimaryScreenReceiver;
class IServer; class IServer;
@ -19,9 +20,11 @@ treated as if it was on a client.
class CPrimaryClient : public IScreenReceiver, public IClient { class CPrimaryClient : public IScreenReceiver, public IClient {
public: public:
/*! /*!
\c name is the name of the server. \c name is the name of the server. the caller retains ownership of
\c factory.
*/ */
CPrimaryClient(IServer*, IPrimaryScreenReceiver*, const CString& name); CPrimaryClient(IPrimaryScreenFactory* factory, IServer*,
IPrimaryScreenReceiver*, const CString& name);
~CPrimaryClient(); ~CPrimaryClient();
//! @name manipulators //! @name manipulators

View File

@ -1,17 +1,19 @@
#include "CServer.h" #include "CServer.h"
#include "CHTTPServer.h" #include "CHTTPServer.h"
#include "CPrimaryClient.h"
#include "IPrimaryScreenFactory.h"
#include "CInputPacketStream.h" #include "CInputPacketStream.h"
#include "COutputPacketStream.h" #include "COutputPacketStream.h"
#include "CPrimaryClient.h"
#include "CProtocolUtil.h" #include "CProtocolUtil.h"
#include "CClientProxy1_0.h" #include "CClientProxy1_0.h"
#include "ProtocolTypes.h" #include "ProtocolTypes.h"
#include "XScreen.h" #include "XScreen.h"
#include "XSynergy.h" #include "XSynergy.h"
#include "CTCPListenSocket.h"
#include "IDataSocket.h" #include "IDataSocket.h"
#include "IListenSocket.h"
#include "ISocketFactory.h" #include "ISocketFactory.h"
#include "XSocket.h" #include "XSocket.h"
#include "IStreamFilterFactory.h"
#include "CLock.h" #include "CLock.h"
#include "CThread.h" #include "CThread.h"
#include "CTimerThread.h" #include "CTimerThread.h"
@ -30,8 +32,9 @@ const SInt32 CServer::s_httpMaxSimultaneousRequests = 3;
CServer::CServer(const CString& serverName) : CServer::CServer(const CString& serverName) :
m_name(serverName), m_name(serverName),
m_bindTimeout(5.0 * 60.0), m_bindTimeout(5.0 * 60.0),
m_screenFactory(NULL),
m_socketFactory(NULL), m_socketFactory(NULL),
m_securityFactory(NULL), m_streamFilterFactory(NULL),
m_acceptClientThread(NULL), m_acceptClientThread(NULL),
m_active(NULL), m_active(NULL),
m_primaryClient(NULL), m_primaryClient(NULL),
@ -45,7 +48,9 @@ CServer::CServer(const CString& serverName) :
CServer::~CServer() CServer::~CServer()
{ {
// do nothing delete m_screenFactory;
delete m_socketFactory;
delete m_streamFilterFactory;
} }
bool bool
@ -179,6 +184,30 @@ CServer::setConfig(const CConfig& config)
return true; return true;
} }
void
CServer::setScreenFactory(IPrimaryScreenFactory* adopted)
{
CLock lock(&m_mutex);
delete m_screenFactory;
m_screenFactory = adopted;
}
void
CServer::setSocketFactory(ISocketFactory* adopted)
{
CLock lock(&m_mutex);
delete m_socketFactory;
m_socketFactory = adopted;
}
void
CServer::setStreamFilterFactory(IStreamFilterFactory* adopted)
{
CLock lock(&m_mutex);
delete m_streamFilterFactory;
m_streamFilterFactory = adopted;
}
CString CString
CServer::getPrimaryScreenName() const CServer::getPrimaryScreenName() const
{ {
@ -695,6 +724,8 @@ CServer::isLockedToScreenNoLock() const
void void
CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver) CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
{ {
// note -- must be locked on entry
assert(dst != NULL); assert(dst != NULL);
#ifndef NDEBUG #ifndef NDEBUG
{ {
@ -706,7 +737,6 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver)
assert(m_active != NULL); assert(m_active != NULL);
log((CLOG_INFO "switch from \"%s\" to \"%s\" at %d,%d", m_active->getName().c_str(), dst->getName().c_str(), x, y)); log((CLOG_INFO "switch from \"%s\" to \"%s\" at %d,%d", m_active->getName().c_str(), dst->getName().c_str(), x, y));
// FIXME -- we're not locked here but we probably should be
// record new position // record new position
m_x = x; m_x = x;
@ -1112,7 +1142,6 @@ CServer::doReapThreads(CThreadList& threads)
} }
} }
#include "CTCPListenSocket.h"
void void
CServer::acceptClients(void*) CServer::acceptClients(void*)
{ {
@ -1121,8 +1150,10 @@ CServer::acceptClients(void*)
IListenSocket* listen = NULL; IListenSocket* listen = NULL;
try { try {
// create socket listener // create socket listener
// listen = std::auto_ptr<IListenSocket>(m_socketFactory->createListen()); if (m_socketFactory != NULL) {
listen = new CTCPListenSocket; // FIXME -- use factory listen = m_socketFactory->createListen();
}
assert(listen != NULL);
// bind to the desired port. keep retrying if we can't bind // bind to the desired port. keep retrying if we can't bind
// the address immediately. // the address immediately.
@ -1242,14 +1273,12 @@ CServer::runClient(void* vsocket)
} }
catch (XBadClient&) { catch (XBadClient&) {
// client not behaving // client not behaving
// FIXME -- could print network address if socket had suitable method
log((CLOG_WARN "protocol error from client \"%s\"", proxy->getName().c_str())); log((CLOG_WARN "protocol error from client \"%s\"", proxy->getName().c_str()));
CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBad); CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBad);
} }
catch (XBase& e) { catch (XBase& e) {
// misc error // misc error
log((CLOG_WARN "error communicating with client \"%s\": %s", proxy->getName().c_str(), e.what())); log((CLOG_WARN "error communicating with client \"%s\": %s", proxy->getName().c_str(), e.what()));
// FIXME -- could print network address if socket had suitable method
} }
catch (...) { catch (...) {
// mainLoop() was probably cancelled // mainLoop() was probably cancelled
@ -1273,13 +1302,11 @@ CServer::handshakeClient(IDataSocket* socket)
IOutputStream* output = socket->getOutputStream(); IOutputStream* output = socket->getOutputStream();
bool own = false; bool own = false;
// attach the encryption layer // attach filters
if (m_securityFactory != NULL) { if (m_streamFilterFactory != NULL) {
/* FIXME -- implement ISecurityFactory input = m_streamFilterFactory->createInput(input, own);
input = m_securityFactory->createInputFilter(input, own); output = m_streamFilterFactory->createOutput(output, own);
output = m_securityFactory->createOutputFilter(output, own);
own = true; own = true;
*/
} }
// attach the packetizing filters // attach the packetizing filters
@ -1293,13 +1320,9 @@ CServer::handshakeClient(IDataSocket* socket)
// give the client a limited time to complete the handshake // give the client a limited time to complete the handshake
CTimerThread timer(30.0); CTimerThread timer(30.0);
// limit the maximum length of the hello
// FIXME -- should be in protocol types; may become obsolete anyway
static const UInt32 maxHelloLen = 1024;
// say hello // say hello
log((CLOG_DEBUG1 "saying hello")); log((CLOG_DEBUG1 "saying hello"));
CProtocolUtil::writef(output, "Synergy%2i%2i", CProtocolUtil::writef(output, kMsgHello,
kProtocolMajorVersion, kProtocolMajorVersion,
kProtocolMinorVersion); kProtocolMinorVersion);
output->flush(); output->flush();
@ -1307,7 +1330,9 @@ CServer::handshakeClient(IDataSocket* socket)
// wait for the reply // wait for the reply
log((CLOG_DEBUG1 "waiting for hello reply")); log((CLOG_DEBUG1 "waiting for hello reply"));
UInt32 n = input->getSize(); UInt32 n = input->getSize();
if (n > maxHelloLen) {
// limit the maximum length of the hello
if (n > kMaxHelloLength) {
throw XBadClient(); throw XBadClient();
} }
@ -1315,7 +1340,7 @@ CServer::handshakeClient(IDataSocket* socket)
SInt16 major, minor; SInt16 major, minor;
try { try {
log((CLOG_DEBUG1 "parsing hello reply")); log((CLOG_DEBUG1 "parsing hello reply"));
CProtocolUtil::readf(input, "Synergy%2i%2i%s", CProtocolUtil::readf(input, kMsgHelloBack,
&major, &minor, &name); &major, &minor, &name);
} }
catch (XIO&) { catch (XIO&) {
@ -1358,21 +1383,18 @@ CServer::handshakeClient(IDataSocket* socket)
} }
catch (XIncompatibleClient& e) { catch (XIncompatibleClient& e) {
// client is incompatible // client is incompatible
// FIXME -- could print network address if socket had suitable method
log((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor())); log((CLOG_WARN "client \"%s\" has incompatible version %d.%d)", name.c_str(), e.getMajor(), e.getMinor()));
CProtocolUtil::writef(output, kMsgEIncompatible, CProtocolUtil::writef(output, kMsgEIncompatible,
kProtocolMajorVersion, kProtocolMinorVersion); kProtocolMajorVersion, kProtocolMinorVersion);
} }
catch (XBadClient&) { catch (XBadClient&) {
// client not behaving // client not behaving
// FIXME -- could print network address if socket had suitable method
log((CLOG_WARN "protocol error from client \"%s\"", name.c_str())); log((CLOG_WARN "protocol error from client \"%s\"", name.c_str()));
CProtocolUtil::writef(output, kMsgEBad); CProtocolUtil::writef(output, kMsgEBad);
} }
catch (XBase& e) { catch (XBase& e) {
// misc error // misc error
log((CLOG_WARN "error communicating with client \"%s\": %s", 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
} }
catch (...) { catch (...) {
// probably timed out // probably timed out
@ -1406,8 +1428,7 @@ CServer::acceptHTTPClients(void*)
IListenSocket* listen = NULL; IListenSocket* listen = NULL;
try { try {
// create socket listener // create socket listener
// listen = std::auto_ptr<IListenSocket>(m_socketFactory->createListen()); listen = new CTCPListenSocket;
listen = new CTCPListenSocket; // FIXME -- use factory
// bind to the desired port. keep retrying if we can't bind // bind to the desired port. keep retrying if we can't bind
// the address immediately. // the address immediately.
@ -1462,7 +1483,6 @@ CServer::acceptHTTPClients(void*)
catch (XBase& e) { catch (XBase& e) {
log((CLOG_ERR "cannot listen for HTTP clients: %s", e.what())); log((CLOG_ERR "cannot listen for HTTP clients: %s", e.what()));
delete listen; delete listen;
// FIXME -- quit?
exitMainLoop(); exitMainLoop();
} }
catch (...) { catch (...) {
@ -1509,20 +1529,21 @@ void
CServer::openPrimaryScreen() CServer::openPrimaryScreen()
{ {
assert(m_primaryClient == NULL); assert(m_primaryClient == NULL);
assert(m_screenFactory != NULL);
// reset sequence number // reset sequence number
m_seqNum = 0; m_seqNum = 0;
// canonicalize the primary screen name // canonicalize the primary screen name
CString primary = m_config.getCanonicalName(getPrimaryScreenName()); CString primaryName = m_config.getCanonicalName(getPrimaryScreenName());
if (primary.empty()) { if (primaryName.empty()) {
throw XUnknownClient(getPrimaryScreenName()); throw XUnknownClient(getPrimaryScreenName());
} }
// clear clipboards // clear clipboards
for (ClipboardID id = 0; id < kClipboardEnd; ++id) { for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
CClipboardInfo& clipboard = m_clipboards[id]; CClipboardInfo& clipboard = m_clipboards[id];
clipboard.m_clipboardOwner = primary; clipboard.m_clipboardOwner = primaryName;
clipboard.m_clipboardSeqNum = m_seqNum; clipboard.m_clipboardSeqNum = m_seqNum;
if (clipboard.m_clipboard.open(0)) { if (clipboard.m_clipboard.open(0)) {
clipboard.m_clipboard.empty(); clipboard.m_clipboard.empty();
@ -1531,9 +1552,10 @@ CServer::openPrimaryScreen()
clipboard.m_clipboardData = clipboard.m_clipboard.marshall(); clipboard.m_clipboardData = clipboard.m_clipboard.marshall();
} }
// create the primary client and open it
try { try {
m_primaryClient = new CPrimaryClient(this, this, primary); // create the primary client
m_primaryClient = new CPrimaryClient(m_screenFactory,
this, this, primaryName);
// add connection // add connection
addConnection(m_primaryClient); addConnection(m_primaryClient);
@ -1548,7 +1570,7 @@ CServer::openPrimaryScreen()
} }
catch (...) { catch (...) {
if (m_active != NULL) { if (m_active != NULL) {
removeConnection(primary); removeConnection(primaryName);
} }
else { else {
delete m_primaryClient; delete m_primaryClient;

View File

@ -16,9 +16,10 @@ class CHTTPServer;
class CPrimaryClient; class CPrimaryClient;
class IClient; class IClient;
class IDataSocket; class IDataSocket;
class IPrimaryScreenFactory;
class IServerProtocol; class IServerProtocol;
class ISocketFactory; class ISocketFactory;
class ISecurityFactory; class IStreamFilterFactory;
//! Synergy server //! Synergy server
/*! /*!
@ -73,6 +74,30 @@ public:
*/ */
bool setConfig(const CConfig&); bool setConfig(const CConfig&);
//! Set primary screen factory
/*!
Sets the factory for creating primary screens. This must be
set before calling open(). This object takes ownership of the
factory.
*/
void setScreenFactory(IPrimaryScreenFactory*);
//! Set socket factory
/*!
Sets the factory used to create a socket to connect to the server.
This must be set before calling mainLoop(). This object takes
ownership of the factory.
*/
void setSocketFactory(ISocketFactory*);
//! Set stream filter factory
/*!
Sets the factory used to filter the socket streams used to
communicate with the server. This object takes ownership
of the factory.
*/
void setStreamFilterFactory(IStreamFilterFactory*);
//@} //@}
//! @name accessors //! @name accessors
//@{ //@{
@ -207,8 +232,10 @@ private:
// how long to wait to bind our socket until we give up // how long to wait to bind our socket until we give up
double m_bindTimeout; double m_bindTimeout;
ISocketFactory* m_socketFactory; // factories
ISecurityFactory* m_securityFactory; IPrimaryScreenFactory* m_screenFactory;
ISocketFactory* m_socketFactory;
IStreamFilterFactory* m_streamFilterFactory;
// running threads // running threads
CThreadList m_threads; CThreadList m_threads;

View File

@ -0,0 +1,25 @@
#ifndef IPRIMARYSCREENFACTORY_H
#define IPRIMARYSCREENFACTORY_H
#include "IInterface.h"
class CPrimaryScreen;
class IPrimaryScreenReceiver;
class IScreenReceiver;
//! Primary screen factory interface
/*!
This interface provides factory methods to create primary screens.
*/
class IPrimaryScreenFactory : public IInterface {
public:
//! Create screen
/*!
Create and return a primary screen. The caller must delete the
returned object.
*/
virtual CPrimaryScreen*
create(IScreenReceiver*, IPrimaryScreenReceiver*) = 0;
};
#endif

View File

@ -20,6 +20,7 @@ libserver_a_SOURCES = \
CPrimaryScreen.h \ CPrimaryScreen.h \
CServer.h \ CServer.h \
CXWindowsPrimaryScreen.h \ CXWindowsPrimaryScreen.h \
IPrimaryScreenFactory.h \
$(NULL) $(NULL)
INCLUDES = \ INCLUDES = \
-I$(DEPTH)/lib/base \ -I$(DEPTH)/lib/base \

View File

@ -8,14 +8,12 @@ libsynergy_a_SOURCES = \
COutputPacketStream.cpp \ COutputPacketStream.cpp \
CProtocolUtil.cpp \ CProtocolUtil.cpp \
CClipboard.cpp \ CClipboard.cpp \
CTCPSocketFactory.cpp \
XScreen.cpp \ XScreen.cpp \
XSynergy.cpp \ XSynergy.cpp \
CClipboard.h \ CClipboard.h \
CInputPacketStream.h \ CInputPacketStream.h \
COutputPacketStream.h \ COutputPacketStream.h \
CProtocolUtil.h \ CProtocolUtil.h \
CTCPSocketFactory.h \
ClipboardTypes.h \ ClipboardTypes.h \
IClient.h \ IClient.h \
IClipboard.h \ IClipboard.h \
@ -25,7 +23,6 @@ libsynergy_a_SOURCES = \
IScreenReceiver.h \ IScreenReceiver.h \
IScreenSaver.h \ IScreenSaver.h \
IServer.h \ IServer.h \
ISocketFactory.h \
KeyTypes.h \ KeyTypes.h \
MouseTypes.h \ MouseTypes.h \
ProtocolTypes.h \ ProtocolTypes.h \

View File

@ -10,6 +10,9 @@ static const SInt16 kProtocolMinorVersion = 7;
// default contact port number // default contact port number
static const UInt16 kDefaultPort = 24800; static const UInt16 kDefaultPort = 24800;
// maximum total length for greeting returned by client
static const UInt32 kMaxHelloLength = 1024;
// time between heartbeats (in seconds) // time between heartbeats (in seconds)
static const double kHeartRate = 2.0; static const double kHeartRate = 2.0;
@ -36,13 +39,30 @@ enum EDirectionMask {
// //
// message codes (trailing NUL is not part of code). in comments, $n // message codes (trailing NUL is not part of code). in comments, $n
// refers to the n'th argument (counting from one). message codes are // refers to the n'th argument (counting from one). message codes are
// always 4 bytes optionally followed by message specific parameters. // always 4 bytes optionally followed by message specific parameters
// except those for the greeting handshake.
// //
// //
// positions and sizes are signed 16 bit integers. // positions and sizes are signed 16 bit integers.
// //
//
// greeting handshake messages
//
// say hello to client; primary -> secondary
// $1 = protocol major version number supported by server. $2 =
// protocol minor version number supported by server.
static const char kMsgHello[] = "Synergy%2i%2i";
// respond to hello from server; secondary -> primary
// $1 = protocol major version number supported by client. $2 =
// protocol minor version number supported by client. $3 = client
// name.
static const char kMsgHelloBack[] = "Synergy%2i%2i%s";
// //
// command codes // command codes
// //