diff --git a/cmd/synergy/synergy.cpp b/cmd/synergy/synergy.cpp index a8b5b3f9..65256702 100644 --- a/cmd/synergy/synergy.cpp +++ b/cmd/synergy/synergy.cpp @@ -1,9 +1,11 @@ #include "CClient.h" +#include "ISecondaryScreenFactory.h" #include "CPlatform.h" #include "ProtocolTypes.h" #include "Version.h" #include "CNetwork.h" #include "CNetworkAddress.h" +#include "CTCPSocketFactory.h" #include "XSocket.h" #include "CCondVar.h" #include "CLock.h" @@ -14,6 +16,12 @@ #include "CString.h" #include +#if WINDOWS_LIKE +#include "CMSWindowsSecondaryScreen.h" +#elif UNIX_LIKE +#include "CXWindowsSecondaryScreen.h" +#endif + // platform dependent name of a daemon #if WINDOWS_LIKE #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 // @@ -87,6 +120,11 @@ realMain(CMutex* mutex) s_client = new CClient(s_name); s_client->camp(s_camp); 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()) { opened = true; diff --git a/cmd/synergyd/synergyd.cpp b/cmd/synergyd/synergyd.cpp index 0a308d34..2db390a3 100644 --- a/cmd/synergyd/synergyd.cpp +++ b/cmd/synergyd/synergyd.cpp @@ -1,9 +1,11 @@ #include "CServer.h" #include "CConfig.h" +#include "IPrimaryScreenFactory.h" #include "CPlatform.h" #include "ProtocolTypes.h" #include "Version.h" #include "CNetwork.h" +#include "CTCPSocketFactory.h" #include "XSocket.h" #include "CLock.h" #include "CMutex.h" @@ -13,6 +15,12 @@ #include "stdfstream.h" #include +#if WINDOWS_LIKE +#include "CMSWindowsPrimaryScreen.h" +#elif UNIX_LIKE +#include "CXWindowsPrimaryScreen.h" +#endif + // platform dependent name of a daemon #if WINDOWS_LIKE #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 // @@ -117,6 +151,11 @@ realMain(CMutex* mutex) // create server s_server = new CServer(s_name); 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()) { opened = true; diff --git a/lib/client/CClient.cpp b/lib/client/CClient.cpp index 54a28ee2..6a70c2f8 100644 --- a/lib/client/CClient.cpp +++ b/lib/client/CClient.cpp @@ -1,5 +1,6 @@ #include "CClient.h" #include "CServerProxy.h" +#include "ISecondaryScreenFactory.h" #include "CClipboard.h" #include "CInputPacketStream.h" #include "COutputPacketStream.h" @@ -9,7 +10,10 @@ #include "ProtocolTypes.h" #include "XScreen.h" #include "XSynergy.h" +#include "IDataSocket.h" +#include "ISocketFactory.h" #include "XSocket.h" +#include "IStreamFilterFactory.h" #include "CLock.h" #include "CThread.h" #include "CTimerThread.h" @@ -27,6 +31,9 @@ CClient::CClient(const CString& clientName) : m_screen(NULL), m_server(NULL), m_camp(false), + m_screenFactory(NULL), + m_socketFactory(NULL), + m_streamFilterFactory(NULL), m_session(NULL), m_active(false), m_rejected(true) @@ -36,7 +43,9 @@ CClient::CClient(const CString& clientName) : CClient::~CClient() { - // do nothing + delete m_screenFactory; + delete m_socketFactory; + delete m_streamFilterFactory; } void @@ -53,6 +62,30 @@ CClient::setAddress(const CNetworkAddress& 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 CClient::exitMainLoop() { @@ -331,16 +364,11 @@ CClient::getCursorCenter(SInt32&, SInt32&) const 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 CClient::openSecondaryScreen() { assert(m_screen == NULL); + assert(m_screenFactory != NULL); // not active m_active = false; @@ -351,15 +379,16 @@ CClient::openSecondaryScreen() m_timeClipboard[id] = 0; } - // open screen + // create screen log((CLOG_DEBUG1 "creating secondary screen")); -#if WINDOWS_LIKE - m_screen = new CMSWindowsSecondaryScreen(this); -#elif UNIX_LIKE - m_screen = new CXWindowsSecondaryScreen(this); -#endif - log((CLOG_DEBUG1 "opening secondary screen")); + m_screen = m_screenFactory->create(this); + if (m_screen == NULL) { + throw XScreenOpenFailure(); + } + + // open screen try { + log((CLOG_DEBUG1 "opening secondary screen")); m_screen->open(); } catch (...) { @@ -459,7 +488,6 @@ CClient::deleteSession(double timeout) } } -#include "CTCPSocket.h" // FIXME void CClient::runServer() { @@ -469,12 +497,14 @@ CClient::runServer() for (;;) { try { // allow connect this much time to succeed - // FIXME -- timeout in member CTimerThread timer(m_camp ? -1.0 : 30.0); // create socket and attempt to connect 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); log((CLOG_INFO "connected to server")); break; @@ -553,14 +583,12 @@ CClient::handshakeServer(IDataSocket* socket) IOutputStream* output = socket->getOutputStream(); bool own = false; - // attach the encryption layer -/* FIXME -- implement ISecurityFactory - if (m_securityFactory != NULL) { - input = m_securityFactory->createInputFilter(input, own); - output = m_securityFactory->createOutputFilter(output, own); + // attach filters + if (m_streamFilterFactory != NULL) { + input = m_streamFilterFactory->createInput(input, own); + output = m_streamFilterFactory->createOutput(output, own); own = true; } -*/ // attach the packetizing filters input = new CInputPacketStream(input, own); @@ -575,7 +603,7 @@ CClient::handshakeServer(IDataSocket* socket) // wait for hello from server log((CLOG_DEBUG1 "wait for hello")); SInt16 major, minor; - CProtocolUtil::readf(input, "Synergy%2i%2i", &major, &minor); + CProtocolUtil::readf(input, kMsgHello, &major, &minor); // check versions log((CLOG_DEBUG1 "got hello version %d.%d", major, minor)); @@ -586,7 +614,7 @@ CClient::handshakeServer(IDataSocket* socket) // say hello back log((CLOG_DEBUG1 "say hello version %d.%d", kProtocolMajorVersion, kProtocolMinorVersion)); - CProtocolUtil::writef(output, "Synergy%2i%2i%s", + CProtocolUtil::writef(output, kMsgHelloBack, kProtocolMajorVersion, kProtocolMinorVersion, &m_name); diff --git a/lib/client/CClient.h b/lib/client/CClient.h index e4be951f..3cfb4543 100644 --- a/lib/client/CClient.h +++ b/lib/client/CClient.h @@ -12,6 +12,9 @@ class CServerProxy; class CThread; class IDataSocket; class IScreenReceiver; +class ISecondaryScreenFactory; +class ISocketFactory; +class IStreamFilterFactory; //! Synergy client /*! @@ -44,6 +47,30 @@ public: */ 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 /*! Force mainLoop() to return. This call can return before @@ -117,6 +144,9 @@ private: IScreenReceiver* m_server; CNetworkAddress m_serverAddress; bool m_camp; + ISecondaryScreenFactory* m_screenFactory; + ISocketFactory* m_socketFactory; + IStreamFilterFactory* m_streamFilterFactory; CThread* m_session; bool m_active; bool m_rejected; diff --git a/lib/client/ISecondaryScreenFactory.h b/lib/client/ISecondaryScreenFactory.h new file mode 100644 index 00000000..57ae3b16 --- /dev/null +++ b/lib/client/ISecondaryScreenFactory.h @@ -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 diff --git a/lib/client/Makefile.am b/lib/client/Makefile.am index 42001eae..c489709c 100644 --- a/lib/client/Makefile.am +++ b/lib/client/Makefile.am @@ -12,6 +12,7 @@ libclient_a_SOURCES = \ CSecondaryScreen.h \ CServerProxy.h \ CXWindowsSecondaryScreen.h \ + ISecondaryScreenFactory.h \ $(NULL) INCLUDES = \ -I$(DEPTH)/lib/base \ diff --git a/lib/io/IStreamFilterFactory.h b/lib/io/IStreamFilterFactory.h new file mode 100644 index 00000000..e7cd50a2 --- /dev/null +++ b/lib/io/IStreamFilterFactory.h @@ -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 diff --git a/lib/io/Makefile.am b/lib/io/Makefile.am index 67ff14a8..6e134dfa 100644 --- a/lib/io/Makefile.am +++ b/lib/io/Makefile.am @@ -17,6 +17,7 @@ libio_a_SOURCES = \ CStreamBuffer.h \ IInputStream.h \ IOutputStream.h \ + IStreamFilterFactory.h \ XIO.h \ $(NULL) INCLUDES = \ diff --git a/lib/synergy/CTCPSocketFactory.cpp b/lib/net/CTCPSocketFactory.cpp similarity index 100% rename from lib/synergy/CTCPSocketFactory.cpp rename to lib/net/CTCPSocketFactory.cpp diff --git a/lib/synergy/CTCPSocketFactory.h b/lib/net/CTCPSocketFactory.h similarity index 100% rename from lib/synergy/CTCPSocketFactory.h rename to lib/net/CTCPSocketFactory.h diff --git a/lib/synergy/ISocketFactory.h b/lib/net/ISocketFactory.h similarity index 100% rename from lib/synergy/ISocketFactory.h rename to lib/net/ISocketFactory.h diff --git a/lib/net/Makefile.am b/lib/net/Makefile.am index f12a316f..cc996705 100644 --- a/lib/net/Makefile.am +++ b/lib/net/Makefile.am @@ -6,17 +6,20 @@ noinst_LIBRARIES = libnet.a libnet_a_SOURCES = \ CNetwork.cpp \ CNetworkAddress.cpp \ - CTCPSocket.cpp \ CTCPListenSocket.cpp \ + CTCPSocket.cpp \ + CTCPSocketFactory.cpp \ XNetwork.cpp \ XSocket.cpp \ CNetwork.h \ CNetworkAddress.h \ CTCPListenSocket.h \ CTCPSocket.h \ + CTCPSocketFactory.h \ IDataSocket.h \ IListenSocket.h \ ISocket.h \ + ISocketFactory.h \ XNetwork.h \ XSocket.h \ $(NULL) diff --git a/lib/server/CPrimaryClient.cpp b/lib/server/CPrimaryClient.cpp index a1e3113d..44f01109 100644 --- a/lib/server/CPrimaryClient.cpp +++ b/lib/server/CPrimaryClient.cpp @@ -1,36 +1,29 @@ #include "CPrimaryClient.h" +#include "IPrimaryScreenFactory.h" #include "IServer.h" #include "XSynergy.h" #include "CPrimaryScreen.h" #include "CClipboard.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(IServer* server, - IPrimaryScreenReceiver* receiver, const CString& name) : +CPrimaryClient::CPrimaryClient(IPrimaryScreenFactory* screenFactory, + IServer* server, + IPrimaryScreenReceiver* receiver, + const CString& name) : m_server(server), m_name(name), m_seqNum(0) { assert(m_server != NULL); + assert(screenFactory != NULL); // create screen log((CLOG_DEBUG1 "creating primary screen")); -#if WINDOWS_LIKE - m_screen = new CMSWindowsPrimaryScreen(this, receiver); -#elif UNIX_LIKE - m_screen = new CXWindowsPrimaryScreen(this, receiver); -#endif + m_screen = screenFactory->create(this, receiver); } CPrimaryClient::~CPrimaryClient() diff --git a/lib/server/CPrimaryClient.h b/lib/server/CPrimaryClient.h index 6631203e..84ea0bad 100644 --- a/lib/server/CPrimaryClient.h +++ b/lib/server/CPrimaryClient.h @@ -7,6 +7,7 @@ class IClipboard; class CPrimaryScreen; +class IPrimaryScreenFactory; class IPrimaryScreenReceiver; class IServer; @@ -19,9 +20,11 @@ treated as if it was on a client. class CPrimaryClient : public IScreenReceiver, public IClient { 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(); //! @name manipulators diff --git a/lib/server/CServer.cpp b/lib/server/CServer.cpp index a4138b1e..822bac97 100644 --- a/lib/server/CServer.cpp +++ b/lib/server/CServer.cpp @@ -1,17 +1,19 @@ #include "CServer.h" #include "CHTTPServer.h" +#include "CPrimaryClient.h" +#include "IPrimaryScreenFactory.h" #include "CInputPacketStream.h" #include "COutputPacketStream.h" -#include "CPrimaryClient.h" #include "CProtocolUtil.h" #include "CClientProxy1_0.h" #include "ProtocolTypes.h" #include "XScreen.h" #include "XSynergy.h" +#include "CTCPListenSocket.h" #include "IDataSocket.h" -#include "IListenSocket.h" #include "ISocketFactory.h" #include "XSocket.h" +#include "IStreamFilterFactory.h" #include "CLock.h" #include "CThread.h" #include "CTimerThread.h" @@ -30,8 +32,9 @@ const SInt32 CServer::s_httpMaxSimultaneousRequests = 3; CServer::CServer(const CString& serverName) : m_name(serverName), m_bindTimeout(5.0 * 60.0), + m_screenFactory(NULL), m_socketFactory(NULL), - m_securityFactory(NULL), + m_streamFilterFactory(NULL), m_acceptClientThread(NULL), m_active(NULL), m_primaryClient(NULL), @@ -45,7 +48,9 @@ CServer::CServer(const CString& serverName) : CServer::~CServer() { - // do nothing + delete m_screenFactory; + delete m_socketFactory; + delete m_streamFilterFactory; } bool @@ -179,6 +184,30 @@ CServer::setConfig(const CConfig& config) 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 CServer::getPrimaryScreenName() const { @@ -695,6 +724,8 @@ CServer::isLockedToScreenNoLock() const void CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver) { + // note -- must be locked on entry + assert(dst != NULL); #ifndef NDEBUG { @@ -706,7 +737,6 @@ CServer::switchScreen(IClient* dst, SInt32 x, SInt32 y, bool forScreensaver) 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)); - // FIXME -- we're not locked here but we probably should be // record new position m_x = x; @@ -1112,7 +1142,6 @@ CServer::doReapThreads(CThreadList& threads) } } -#include "CTCPListenSocket.h" void CServer::acceptClients(void*) { @@ -1121,8 +1150,10 @@ CServer::acceptClients(void*) IListenSocket* listen = NULL; try { // create socket listener -// listen = std::auto_ptr(m_socketFactory->createListen()); - listen = new CTCPListenSocket; // FIXME -- use factory + if (m_socketFactory != NULL) { + listen = m_socketFactory->createListen(); + } + assert(listen != NULL); // bind to the desired port. keep retrying if we can't bind // the address immediately. @@ -1242,14 +1273,12 @@ CServer::runClient(void* vsocket) } catch (XBadClient&) { // 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())); CProtocolUtil::writef(proxy->getOutputStream(), kMsgEBad); } catch (XBase& e) { // misc error 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 (...) { // mainLoop() was probably cancelled @@ -1273,13 +1302,11 @@ CServer::handshakeClient(IDataSocket* socket) IOutputStream* output = socket->getOutputStream(); bool own = false; - // attach the encryption layer - if (m_securityFactory != NULL) { -/* FIXME -- implement ISecurityFactory - input = m_securityFactory->createInputFilter(input, own); - output = m_securityFactory->createOutputFilter(output, own); + // attach filters + if (m_streamFilterFactory != NULL) { + input = m_streamFilterFactory->createInput(input, own); + output = m_streamFilterFactory->createOutput(output, own); own = true; -*/ } // attach the packetizing filters @@ -1293,13 +1320,9 @@ CServer::handshakeClient(IDataSocket* socket) // give the client a limited time to complete the handshake 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 log((CLOG_DEBUG1 "saying hello")); - CProtocolUtil::writef(output, "Synergy%2i%2i", + CProtocolUtil::writef(output, kMsgHello, kProtocolMajorVersion, kProtocolMinorVersion); output->flush(); @@ -1307,7 +1330,9 @@ CServer::handshakeClient(IDataSocket* socket) // wait for the reply log((CLOG_DEBUG1 "waiting for hello reply")); UInt32 n = input->getSize(); - if (n > maxHelloLen) { + + // limit the maximum length of the hello + if (n > kMaxHelloLength) { throw XBadClient(); } @@ -1315,7 +1340,7 @@ CServer::handshakeClient(IDataSocket* socket) SInt16 major, minor; try { log((CLOG_DEBUG1 "parsing hello reply")); - CProtocolUtil::readf(input, "Synergy%2i%2i%s", + CProtocolUtil::readf(input, kMsgHelloBack, &major, &minor, &name); } catch (XIO&) { @@ -1358,21 +1383,18 @@ CServer::handshakeClient(IDataSocket* socket) } catch (XIncompatibleClient& e) { // 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())); CProtocolUtil::writef(output, kMsgEIncompatible, kProtocolMajorVersion, kProtocolMinorVersion); } catch (XBadClient&) { // client not behaving - // FIXME -- could print network address if socket had suitable method log((CLOG_WARN "protocol error from client \"%s\"", name.c_str())); CProtocolUtil::writef(output, kMsgEBad); } catch (XBase& e) { // misc error 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 (...) { // probably timed out @@ -1406,8 +1428,7 @@ CServer::acceptHTTPClients(void*) IListenSocket* listen = NULL; try { // create socket listener -// listen = std::auto_ptr(m_socketFactory->createListen()); - listen = new CTCPListenSocket; // FIXME -- use factory + listen = new CTCPListenSocket; // bind to the desired port. keep retrying if we can't bind // the address immediately. @@ -1462,7 +1483,6 @@ CServer::acceptHTTPClients(void*) catch (XBase& e) { log((CLOG_ERR "cannot listen for HTTP clients: %s", e.what())); delete listen; - // FIXME -- quit? exitMainLoop(); } catch (...) { @@ -1509,20 +1529,21 @@ void CServer::openPrimaryScreen() { assert(m_primaryClient == NULL); + assert(m_screenFactory != NULL); // reset sequence number m_seqNum = 0; // canonicalize the primary screen name - CString primary = m_config.getCanonicalName(getPrimaryScreenName()); - if (primary.empty()) { + CString primaryName = m_config.getCanonicalName(getPrimaryScreenName()); + if (primaryName.empty()) { throw XUnknownClient(getPrimaryScreenName()); } // clear clipboards for (ClipboardID id = 0; id < kClipboardEnd; ++id) { CClipboardInfo& clipboard = m_clipboards[id]; - clipboard.m_clipboardOwner = primary; + clipboard.m_clipboardOwner = primaryName; clipboard.m_clipboardSeqNum = m_seqNum; if (clipboard.m_clipboard.open(0)) { clipboard.m_clipboard.empty(); @@ -1531,9 +1552,10 @@ CServer::openPrimaryScreen() clipboard.m_clipboardData = clipboard.m_clipboard.marshall(); } - // create the primary client and open it try { - m_primaryClient = new CPrimaryClient(this, this, primary); + // create the primary client + m_primaryClient = new CPrimaryClient(m_screenFactory, + this, this, primaryName); // add connection addConnection(m_primaryClient); @@ -1548,7 +1570,7 @@ CServer::openPrimaryScreen() } catch (...) { if (m_active != NULL) { - removeConnection(primary); + removeConnection(primaryName); } else { delete m_primaryClient; diff --git a/lib/server/CServer.h b/lib/server/CServer.h index 43d58879..a119fa6a 100644 --- a/lib/server/CServer.h +++ b/lib/server/CServer.h @@ -16,9 +16,10 @@ class CHTTPServer; class CPrimaryClient; class IClient; class IDataSocket; +class IPrimaryScreenFactory; class IServerProtocol; class ISocketFactory; -class ISecurityFactory; +class IStreamFilterFactory; //! Synergy server /*! @@ -73,6 +74,30 @@ public: */ 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 //@{ @@ -207,8 +232,10 @@ private: // how long to wait to bind our socket until we give up double m_bindTimeout; - ISocketFactory* m_socketFactory; - ISecurityFactory* m_securityFactory; + // factories + IPrimaryScreenFactory* m_screenFactory; + ISocketFactory* m_socketFactory; + IStreamFilterFactory* m_streamFilterFactory; // running threads CThreadList m_threads; diff --git a/lib/server/IPrimaryScreenFactory.h b/lib/server/IPrimaryScreenFactory.h new file mode 100644 index 00000000..ccb62951 --- /dev/null +++ b/lib/server/IPrimaryScreenFactory.h @@ -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 diff --git a/lib/server/Makefile.am b/lib/server/Makefile.am index 36f6e393..db86137b 100644 --- a/lib/server/Makefile.am +++ b/lib/server/Makefile.am @@ -20,6 +20,7 @@ libserver_a_SOURCES = \ CPrimaryScreen.h \ CServer.h \ CXWindowsPrimaryScreen.h \ + IPrimaryScreenFactory.h \ $(NULL) INCLUDES = \ -I$(DEPTH)/lib/base \ diff --git a/lib/synergy/Makefile.am b/lib/synergy/Makefile.am index 55adf09e..de13e200 100644 --- a/lib/synergy/Makefile.am +++ b/lib/synergy/Makefile.am @@ -8,14 +8,12 @@ libsynergy_a_SOURCES = \ COutputPacketStream.cpp \ CProtocolUtil.cpp \ CClipboard.cpp \ - CTCPSocketFactory.cpp \ XScreen.cpp \ XSynergy.cpp \ CClipboard.h \ CInputPacketStream.h \ COutputPacketStream.h \ CProtocolUtil.h \ - CTCPSocketFactory.h \ ClipboardTypes.h \ IClient.h \ IClipboard.h \ @@ -25,7 +23,6 @@ libsynergy_a_SOURCES = \ IScreenReceiver.h \ IScreenSaver.h \ IServer.h \ - ISocketFactory.h \ KeyTypes.h \ MouseTypes.h \ ProtocolTypes.h \ diff --git a/lib/synergy/ProtocolTypes.h b/lib/synergy/ProtocolTypes.h index 3e14cd13..7417b270 100644 --- a/lib/synergy/ProtocolTypes.h +++ b/lib/synergy/ProtocolTypes.h @@ -10,6 +10,9 @@ static const SInt16 kProtocolMinorVersion = 7; // default contact port number static const UInt16 kDefaultPort = 24800; +// maximum total length for greeting returned by client +static const UInt32 kMaxHelloLength = 1024; + // time between heartbeats (in seconds) static const double kHeartRate = 2.0; @@ -36,13 +39,30 @@ enum EDirectionMask { // // message codes (trailing NUL is not part of code). in comments, $n // 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. // +// +// 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 //