From 555aa19eb21e4ffa70196e86377b5f05e9a5f156 Mon Sep 17 00:00:00 2001 From: crs Date: Sun, 9 Jun 2002 16:53:25 +0000 Subject: [PATCH] added command line and configuration file arguments to choose the address and port to listen on or connect to. changed the default port and put it in ProtocolTypes.h. the HTTP port is now no longer opened unless the --http argument is supplied or the config file includes it. --- client/client.cpp | 35 +++++++++---- net/CNetwork.cpp | 52 +++++++++++++------ net/CNetwork.h | 12 +++-- net/CNetworkAddress.cpp | 110 ++++++++++++++++++++++++++++++++++++---- net/CNetworkAddress.h | 27 ++++++++-- net/XSocket.cpp | 4 +- net/XSocket.h | 6 +-- server/CConfig.cpp | 94 +++++++++++++++++++++++++++++++++- server/CConfig.h | 13 +++++ server/CHTTPServer.cpp | 3 ++ server/CServer.cpp | 18 +++---- server/CServer.h | 1 + server/server.cpp | 60 ++++++++++++++++++++-- synergy/ProtocolTypes.h | 3 ++ 14 files changed, 376 insertions(+), 62 deletions(-) diff --git a/client/client.cpp b/client/client.cpp index 6297ad38..b34010a0 100644 --- a/client/client.cpp +++ b/client/client.cpp @@ -32,7 +32,7 @@ static bool s_daemon = true; static bool s_install = false; static bool s_uninstall = false; static const char* s_logFilter = NULL; -static const char* s_serverName = NULL; +static CNetworkAddress s_serverAddress; // @@ -62,8 +62,6 @@ static CClient* s_client = NULL; static int realMain(CMutex* mutex) { - static const UInt16 port = 50001; // FIXME - try { // initialize threading library CThread::init(); @@ -75,11 +73,7 @@ static int realMain(CMutex* mutex) bool locked = true; try { - // initialize network library - CNetwork::init(); - // create client - CNetworkAddress addr(s_serverName, port); s_client = new CClient("secondary"); // FIXME // run client @@ -87,7 +81,7 @@ static int realMain(CMutex* mutex) mutex->unlock(); } locked = false; - s_client->run(addr); + s_client->run(s_serverAddress); locked = true; if (mutex != NULL) { mutex->lock(); @@ -194,9 +188,13 @@ static void help() "\n" "* marks defaults.\n" "\n" +"The server address is of the form: [][:]. The hostname\n" +"must be the address or hostname of the server. The port overrides the\n" +"default port, %d.\n" +"\n" "Where log messages go depends on the platform and whether or not the\n" "client is running as a "DAEMON".", - pname)); + pname, kDefaultPort)); } @@ -334,7 +332,16 @@ static void parse(int argc, const char** argv) pname, argv[i], pname)); bye(2); } - s_serverName = argv[i]; + + // save server address + try { + s_serverAddress = CNetworkAddress(argv[i], kDefaultPort); + } + catch (XSocketAddress&) { + log((CLOG_PRINT "%s: invalid server address" BYE, + pname, pname)); + bye(2); + } } // increase default filter level for daemon. the user must @@ -445,6 +452,9 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) // get program name pname = platform.getBasename(__argv[0]); + // initialize network library + CNetwork::init(); + // parse command line without reporting errors but recording if // the app would've exited. this is too avoid showing a dialog // box if we're being started as a service because we shouldn't @@ -504,7 +514,7 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) commandLine += s_logFilter; } commandLine += " "; - commandLine += s_serverName; + commandLine += s_serverAddress.getHostname().c_str(); // install if (!platform.installDaemon(DAEMON_NAME, @@ -560,6 +570,9 @@ int main(int argc, char** argv) // get program name pname = platform.getBasename(argv[0]); + // initialize network library + CNetwork::init(); + // parse command line parse(argc, const_cast(argv)); diff --git a/net/CNetwork.cpp b/net/CNetwork.cpp index 6bbf7511..30f68913 100644 --- a/net/CNetwork.cpp +++ b/net/CNetwork.cpp @@ -15,13 +15,9 @@ int (PASCAL FAR *CNetwork::ioctl)(CNetwork::Socket s, int cmd, ...); int (PASCAL FAR *CNetwork::getpeername)(CNetwork::Socket s, CNetwork::Address FAR *name, CNetwork::AddressLength FAR * namelen); int (PASCAL FAR *CNetwork::getsockname)(CNetwork::Socket s, CNetwork::Address FAR *name, CNetwork::AddressLength FAR * namelen); int (PASCAL FAR *CNetwork::getsockopt)(CNetwork::Socket s, int level, int optname, void FAR * optval, CNetwork::AddressLength FAR *optlen); -UInt32 (PASCAL FAR *CNetwork::swaphtonl)(UInt32 hostlong); -UInt16 (PASCAL FAR *CNetwork::swaphtons)(UInt16 hostshort); unsigned long (PASCAL FAR *CNetwork::inet_addr)(const char FAR * cp); char FAR * (PASCAL FAR *CNetwork::inet_ntoa)(struct in_addr in); int (PASCAL FAR *CNetwork::listen)(CNetwork::Socket s, int backlog); -UInt32 (PASCAL FAR *CNetwork::swapntohl)(UInt32 netlong); -UInt16 (PASCAL FAR *CNetwork::swapntohs)(UInt16 netshort); ssize_t (PASCAL FAR *CNetwork::read)(CNetwork::Socket s, void FAR * buf, size_t len); ssize_t (PASCAL FAR *CNetwork::recv)(CNetwork::Socket s, void FAR * buf, size_t len, int flags); ssize_t (PASCAL FAR *CNetwork::recvfrom)(CNetwork::Socket s, void FAR * buf, size_t len, int flags, CNetwork::Address FAR *from, CNetwork::AddressLength FAR * fromlen); @@ -113,6 +109,38 @@ void CNetwork::cleanup() } } +UInt32 CNetwork::swaphtonl(UInt32 v) +{ + static const union { UInt16 s; UInt8 b[2]; } s_endian = { 0x1234 }; + if (s_endian.b[0] == 0x34) + return ((v & 0xff000000lu) >> 24) | + ((v & 0x00ff0000lu) >> 8) | + ((v & 0x0000ff00lu) << 8) | + ((v & 0x000000fflu) << 24); + else + return v; +} + +UInt16 CNetwork::swaphtons(UInt16 v) +{ + static const union { UInt16 s; UInt8 b[2]; } s_endian = { 0x1234 }; + if (s_endian.b[0] == 0x34) + return ((v & 0xff00u) >> 8) | + ((v & 0x00ffu) << 8); + else + return v; +} + +UInt32 CNetwork::swapntohl(UInt32 v) +{ + return swaphtonl(v); +} + +UInt16 CNetwork::swapntohs(UInt16 v) +{ + return swaphtons(v); +} + #define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name) void CNetwork::init2(HMODULE module) @@ -141,13 +169,9 @@ void CNetwork::init2(HMODULE module) setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen)); setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen)); setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen)); - setfunc(swaphtonl, htonl, UInt32 (PASCAL FAR *)(UInt32 hostlong)); - setfunc(swaphtons, htons, UInt16 (PASCAL FAR *)(UInt16 hostshort)); setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp)); setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in)); setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog)); - setfunc(swapntohl, ntohl, UInt32 (PASCAL FAR *)(UInt32 netlong)); - setfunc(swapntohs, ntohs, UInt16 (PASCAL FAR *)(UInt16 netshort)); setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags)); setfunc(recvfrom, recvfrom, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen)); setfunc(send, send, ssize_t (PASCAL FAR *)(Socket s, const void FAR * buf, size_t len, int flags)); @@ -259,22 +283,22 @@ ssize_t PASCAL FAR CNetwork::write2(Socket s, #define setfunc(var, name, type) var = (type)::name -static UInt32 myhtonl(UInt32 v) +UInt32 CNetwork::swaphtonl(UInt32 v) { return htonl(v); } -static UInt16 myhtons(UInt16 v) +UInt16 CNetwork::swaphtons(UInt16 v) { return htons(v); } -static UInt32 myntohl(UInt32 v) +UInt32 CNetwork::swapntohl(UInt32 v) { return ntohl(v); } -static UInt16 myntohs(UInt16 v) +UInt16 CNetwork::swapntohs(UInt16 v) { return ntohs(v); } @@ -307,13 +331,9 @@ void CNetwork::init() setfunc(getpeername, getpeername, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen)); setfunc(getsockname, getsockname, int (PASCAL FAR *)(Socket s, Address FAR *name, AddressLength FAR * namelen)); setfunc(getsockopt, getsockopt, int (PASCAL FAR *)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen)); - setfunc(swaphtonl, myhtonl, UInt32 (PASCAL FAR *)(UInt32 hostlong)); - setfunc(swaphtons, myhtons, UInt16 (PASCAL FAR *)(UInt16 hostshort)); setfunc(inet_addr, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp)); setfunc(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in)); setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog)); - setfunc(swapntohl, myntohl, UInt32 (PASCAL FAR *)(UInt32 netlong)); - setfunc(swapntohs, myntohs, UInt16 (PASCAL FAR *)(UInt16 netshort)); setfunc(poll, poll, int (PASCAL FAR *)(CNetwork::PollEntry fds[], int nfds, int timeout)); setfunc(read, read, ssize_t (PASCAL FAR *)(CNetwork::Socket s, void FAR * buf, size_t len)); setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags)); diff --git a/net/CNetwork.h b/net/CNetwork.h index 696973da..1fa01afa 100644 --- a/net/CNetwork.h +++ b/net/CNetwork.h @@ -69,6 +69,12 @@ public: static void init(); static void cleanup(); + // byte swapping functions + static UInt32 swaphtonl(UInt32 hostlong); + static UInt16 swaphtons(UInt16 hostshort); + static UInt32 swapntohl(UInt32 netlong); + static UInt16 swapntohs(UInt16 netshort); + // constants static const int Error; @@ -100,7 +106,7 @@ public: kHNone = 0 }; - // socket interface + // socket interface (only available after init()) static Socket (PASCAL FAR *accept)(Socket s, Address FAR *addr, AddressLength FAR *addrlen); static int (PASCAL FAR *bind)(Socket s, const Address FAR *addr, AddressLength namelen); @@ -110,13 +116,9 @@ public: static int (PASCAL FAR *getpeername)(Socket s, Address FAR *name, AddressLength FAR * namelen); static int (PASCAL FAR *getsockname)(Socket s, Address FAR *name, AddressLength FAR * namelen); static int (PASCAL FAR *getsockopt)(Socket s, int level, int optname, void FAR * optval, AddressLength FAR *optlen); - static UInt32 (PASCAL FAR *swaphtonl)(UInt32 hostlong); - static UInt16 (PASCAL FAR *swaphtons)(UInt16 hostshort); static unsigned long (PASCAL FAR *inet_addr)(const char FAR * cp); static char FAR * (PASCAL FAR *inet_ntoa)(struct in_addr in); static int (PASCAL FAR *listen)(Socket s, int backlog); - static UInt32 (PASCAL FAR *swapntohl)(UInt32 netlong); - static UInt16 (PASCAL FAR *swapntohs)(UInt16 netshort); static ssize_t (PASCAL FAR *read)(Socket s, void FAR * buf, size_t len); static ssize_t (PASCAL FAR *recv)(Socket s, void FAR * buf, size_t len, int flags); static ssize_t (PASCAL FAR *recvfrom)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen); diff --git a/net/CNetworkAddress.cpp b/net/CNetworkAddress.cpp index 1d832475..0e07605e 100644 --- a/net/CNetworkAddress.cpp +++ b/net/CNetworkAddress.cpp @@ -1,26 +1,102 @@ #include "CNetworkAddress.h" +#include "CString.h" +#include // // CNetworkAddress // -CNetworkAddress::CNetworkAddress(UInt16 port) +CNetworkAddress::CNetworkAddress() : m_port(0) { - if (port == 0) - throw XSocketAddress(XSocketAddress::kBadPort, CString(), port); + // note -- make no calls to CNetwork socket interface here; + // we're often called prior to CNetwork::init(). - struct sockaddr_in* inetAddress = reinterpret_cast(&m_address); + struct sockaddr_in* inetAddress = reinterpret_cast< + struct sockaddr_in*>(&m_address); inetAddress->sin_family = AF_INET; - inetAddress->sin_port = CNetwork::swaphtons(port); + inetAddress->sin_port = CNetwork::swaphtons(m_port); inetAddress->sin_addr.s_addr = INADDR_ANY; memset(inetAddress->sin_zero, 0, sizeof(inetAddress->sin_zero)); } -CNetworkAddress::CNetworkAddress(const CString& hostname, UInt16 port) +CNetworkAddress::CNetworkAddress(UInt16 port) : m_port(port) { - if (port == 0) - throw XSocketAddress(XSocketAddress::kBadPort, hostname, port); + if (port == 0) { + throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, m_port); + } + struct sockaddr_in* inetAddress = reinterpret_cast< + struct sockaddr_in*>(&m_address); + inetAddress->sin_family = AF_INET; + inetAddress->sin_port = CNetwork::swaphtons(m_port); + inetAddress->sin_addr.s_addr = INADDR_ANY; + memset(inetAddress->sin_zero, 0, sizeof(inetAddress->sin_zero)); +} + +CNetworkAddress::CNetworkAddress(const CString& hostname_, UInt16 port) : + m_hostname(hostname_), + m_port(port) +{ + CString hostname(m_hostname); + + if (port == 0) { + throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, m_port); + } + + // check for port suffix + CString::size_type i = hostname.rfind(':'); + if (i != CString::npos && i + 1 < hostname.size()) { + // found a colon. see if it looks like an IPv6 address. + bool colonNotation = false; + bool dotNotation = false; + bool doubleColon = false; + for (CString::size_type j = 0; j < i; ++j) { + if (hostname[j] == ':') { + colonNotation = true; + dotNotation = false; + if (hostname[j + 1] == ':') { + doubleColon = true; + } + } + else if (hostname[j] == '.' && colonNotation) { + dotNotation = true; + } + } + + // port suffix is ambiguous with IPv6 notation if there's + // a double colon and the end of the address is not in dot + // notation. in that case we assume it's not a port suffix. + // the user can replace the double colon with zeros to + // disambiguate. + if ((!doubleColon || dotNotation) || !colonNotation) { + char* end; + long suffixPort = strtol(hostname.c_str() + i + 1, &end, 10); + if (end == hostname.c_str() + i + 1 || *end != '\0' || + suffixPort <= 0 || suffixPort > 65535) { + // bogus port + throw XSocketAddress(XSocketAddress::kBadPort, + m_hostname, m_port); + } + else { + // good port + port = static_cast(suffixPort); + hostname.erase(i); + } + } + } + + // if hostname is empty then use wildcard address + if (hostname.empty()) { + struct sockaddr_in* inetAddress = reinterpret_cast< + struct sockaddr_in*>(&m_address); + inetAddress->sin_family = AF_INET; + inetAddress->sin_port = CNetwork::swaphtons(port); + inetAddress->sin_addr.s_addr = INADDR_ANY; + memset(inetAddress->sin_zero, 0, sizeof(inetAddress->sin_zero)); + return; + } + + // look up name struct hostent* hent = CNetwork::gethostbyname(hostname.c_str()); if (hent == NULL) { switch (CNetwork::gethosterror()) { @@ -37,7 +113,8 @@ CNetworkAddress::CNetworkAddress(const CString& hostname, UInt16 port) } } - struct sockaddr_in* inetAddress = reinterpret_cast(&m_address); + struct sockaddr_in* inetAddress = reinterpret_cast< + struct sockaddr_in*>(&m_address); inetAddress->sin_family = hent->h_addrtype; inetAddress->sin_port = CNetwork::swaphtons(port); memcpy(&inetAddress->sin_addr, hent->h_addr_list[0], hent->h_length); @@ -49,6 +126,11 @@ CNetworkAddress::~CNetworkAddress() // do nothing } +bool CNetworkAddress::isValid() const +{ + return (m_port != 0); +} + const CNetwork::Address* CNetworkAddress::getAddress() const { return &m_address; @@ -58,3 +140,13 @@ CNetwork::AddressLength CNetworkAddress::getAddressLength() const { return sizeof(m_address); } + +CString CNetworkAddress::getHostname() const +{ + return m_hostname; +} + +UInt16 CNetworkAddress::getPort() const +{ + return m_port; +} diff --git a/net/CNetworkAddress.h b/net/CNetworkAddress.h index 6b1729d5..08750e29 100644 --- a/net/CNetworkAddress.h +++ b/net/CNetworkAddress.h @@ -1,27 +1,48 @@ #ifndef CNETWORKADDRESS_H #define CNETWORKADDRESS_H -#include "BasicTypes.h" #include "CNetwork.h" #include "XSocket.h" - -class CString; +#include "CString.h" +#include "BasicTypes.h" class CNetworkAddress { public: + // invalid address + CNetworkAddress(); + + // wildcard address and given port. port must not be zero. CNetworkAddress(UInt16 port); + + // given address and port. if hostname can be parsed as numerical + // address then that's how it's used, otherwise the hostname is + // looked up. if lookup fails then it throws XSocketAddress. if + // hostname ends in ":[0-9]+" then that suffix is extracted and + // used as the port, overridding the port parameter. neither + // port may be zero. CNetworkAddress(const CString& hostname, UInt16 port); + ~CNetworkAddress(); // manipulators // accessors + // returns true if this is not the invalid address + bool isValid() const; + + // get the address const CNetwork::Address* getAddress() const; CNetwork::AddressLength getAddressLength() const; + // get the hostname and port (as provided in the c'tor) + CString getHostname() const; + UInt16 getPort() const; + private: CNetwork::Address m_address; + CString m_hostname; + UInt16 m_port; }; #endif diff --git a/net/XSocket.cpp b/net/XSocket.cpp index d5478908..983e9eae 100644 --- a/net/XSocket.cpp +++ b/net/XSocket.cpp @@ -5,7 +5,7 @@ // XSocketAddress::XSocketAddress(Error error, - const CString& hostname, SInt16 port) throw() : + const CString& hostname, UInt16 port) throw() : m_error(error), m_hostname(hostname), m_port(port) @@ -23,7 +23,7 @@ CString XSocketAddress::getHostname() const throw() return m_hostname; } -SInt16 XSocketAddress::getPort() const throw() +UInt16 XSocketAddress::getPort() const throw() { return m_port; } diff --git a/net/XSocket.h b/net/XSocket.h index 7a5cc6f5..1a83c99d 100644 --- a/net/XSocket.h +++ b/net/XSocket.h @@ -11,13 +11,13 @@ class XSocketAddress : public XSocket { public: enum Error { kUnknown, kNotFound, kNoAddress, kBadPort }; - XSocketAddress(Error, const CString& hostname, SInt16 port) throw(); + XSocketAddress(Error, const CString& hostname, UInt16 port) throw(); // accessors virtual Error getError() const throw(); virtual CString getHostname() const throw(); - virtual SInt16 getPort() const throw(); + virtual UInt16 getPort() const throw(); protected: // XBase overrides @@ -26,7 +26,7 @@ protected: private: Error m_error; CString m_hostname; - SInt16 m_port; + UInt16 m_port; }; class XSocketErrno : public XSocket, public MXErrno { diff --git a/server/CConfig.cpp b/server/CConfig.cpp index 84f8789c..4d82366d 100644 --- a/server/CConfig.cpp +++ b/server/CConfig.cpp @@ -1,4 +1,5 @@ #include "CConfig.h" +#include "ProtocolTypes.h" #include "stdistream.h" #include "stdostream.h" #include @@ -156,6 +157,16 @@ bool CConfig::disconnect(const CString& srcName, return true; } +void CConfig::setSynergyAddress(const CNetworkAddress& addr) +{ + m_synergyAddress = addr; +} + +void CConfig::setHTTPAddress(const CNetworkAddress& addr) +{ + m_httpAddress = addr; +} + bool CConfig::isValidScreenName(const CString& name) const { // name is valid if matches validname @@ -245,6 +256,16 @@ CString CConfig::getNeighbor(const CString& srcName, srcSide - kFirstDirection]); } +const CNetworkAddress& CConfig::getSynergyAddress() const +{ + return m_synergyAddress; +} + +const CNetworkAddress& CConfig::getHTTPAddress() const +{ + return m_httpAddress; +} + const char* CConfig::dirName(EDirection dir) { static const char* s_name[] = { "left", "right", "top", "bottom" }; @@ -277,6 +298,7 @@ bool CConfig::readLine(std::istream& s, CString& line) void CConfig::readSection(std::istream& s) { static const char s_section[] = "section:"; + static const char s_network[] = "network"; static const char s_screens[] = "screens"; static const char s_links[] = "links"; static const char s_aliases[] = "aliases"; @@ -304,7 +326,10 @@ void CConfig::readSection(std::istream& s) } // read section - if (name == s_screens) { + if (name == s_network) { + readSectionNetwork(s); + } + else if (name == s_screens) { readSectionScreens(s); } else if (name == s_links) { @@ -318,6 +343,61 @@ void CConfig::readSection(std::istream& s) } } +void CConfig::readSectionNetwork(std::istream& s) +{ + CString line; + CString name; + while (readLine(s, line)) { + // check for end of section + if (line == "end") { + return; + } + + // parse argument: `=' + CString::size_type i = line.find_first_of(" \t="); + if (i == 0) { + throw XConfigRead("missing argument name"); + } + if (i == CString::npos) { + throw XConfigRead("missing = in argument"); + } + CString name = line.substr(0, i); + i = line.find_first_not_of(" \t", i); + if (i == CString::npos || line[i] != '=') { + throw XConfigRead("missing = in argument"); + } + i = line.find_first_not_of(" \t", i + 1); + CString value; + if (i != CString::npos) { + value = line.substr(i); + } + if (value.empty()) { + throw XConfigRead("missing value after ="); + } + + if (name == "address") { + try { + m_synergyAddress = CNetworkAddress(value, kDefaultPort); + } + catch (XSocketAddress&) { + throw XConfigRead("invalid address argument"); + } + } + else if (name == "http") { + try { + m_httpAddress = CNetworkAddress(value, kDefaultPort + 1); + } + catch (XSocketAddress&) { + throw XConfigRead("invalid http argument"); + } + } + else { + throw XConfigRead("unknown argument"); + } + } + throw XConfigRead("unexpected end of screens section"); +} + void CConfig::readSectionScreens(std::istream& s) { CString line; @@ -493,6 +573,18 @@ std::istream& operator>>(std::istream& s, CConfig& config) std::ostream& operator<<(std::ostream& s, const CConfig& config) { + // network section + s << "section: network" << std::endl; + if (config.m_synergyAddress.isValid()) { + s << "\taddress=" << config.m_synergyAddress.getHostname().c_str() << + std::endl; + } + if (config.m_httpAddress.isValid()) { + s << "\thttp=" << config.m_httpAddress.getHostname().c_str() << + std::endl; + } + s << "end" << std::endl; + // screens section s << "section: screens" << std::endl; for (CConfig::const_iterator screen = config.begin(); diff --git a/server/CConfig.h b/server/CConfig.h index f97c7a0a..73f4a911 100644 --- a/server/CConfig.h +++ b/server/CConfig.h @@ -3,6 +3,7 @@ #include "BasicTypes.h" #include "CString.h" +#include "CNetworkAddress.h" #include "XBase.h" #include #include "stdmap.h" @@ -96,6 +97,11 @@ public: bool disconnect(const CString& srcName, EDirection srcSide); + // set the synergy and http listen addresses. there are no + // default addresses. + void setSynergyAddress(const CNetworkAddress&); + void setHTTPAddress(const CNetworkAddress&); + // accessors // returns true iff the given name is a valid screen name. @@ -120,6 +126,10 @@ public: // screen name. CString getNeighbor(const CString&, EDirection) const; + // get the listen addresses + const CNetworkAddress& getSynergyAddress() const; + const CNetworkAddress& getHTTPAddress() const; + // read/write a configuration. operator>> will throw XConfigRead // on error. friend std::istream& operator>>(std::istream&, CConfig&); @@ -131,6 +141,7 @@ public: private: static bool readLine(std::istream&, CString&); void readSection(std::istream&); + void readSectionNetwork(std::istream&); void readSectionScreens(std::istream&); void readSectionLinks(std::istream&); void readSectionAliases(std::istream&); @@ -140,6 +151,8 @@ private: CCellMap m_map; CNameMap m_nameToCanonicalName; + CNetworkAddress m_synergyAddress; + CNetworkAddress m_httpAddress; }; class XConfigRead : public XBase { diff --git a/server/CHTTPServer.cpp b/server/CHTTPServer.cpp index d85b0978..95cb6d43 100644 --- a/server/CHTTPServer.cpp +++ b/server/CHTTPServer.cpp @@ -308,6 +308,7 @@ void CHTTPServer::doProcessPostEditMap( // convert temporary screen map into a regular map CConfig config; + m_server->getConfig(&config); screens.convertTo(config); // set new screen map on server @@ -719,6 +720,8 @@ bool CHTTPServer::CScreenArray::convertFrom( void CHTTPServer::CScreenArray::convertTo( CConfig& config) const { + config.removeAllScreens(); + // add screens and find smallest box containing all screens SInt32 x0 = m_w, x1 = 0, y0 = m_h, y1 = 0; for (SInt32 y = 0; y < m_h; ++y) { diff --git a/server/CServer.cpp b/server/CServer.cpp index 85e65179..475bf5ef 100644 --- a/server/CServer.cpp +++ b/server/CServer.cpp @@ -83,13 +83,15 @@ void CServer::run() } } - // start listening for HTTP requests - m_httpServer = new CHTTPServer(this); - CThread(new TMethodJob(this, &CServer::acceptHTTPClients)); - // start listening for new clients CThread(new TMethodJob(this, &CServer::acceptClients)); + // start listening for HTTP requests + if (m_config.getHTTPAddress().isValid()) { + m_httpServer = new CHTTPServer(this); + CThread(new TMethodJob(this, &CServer::acceptHTTPClients)); + } + // handle events log((CLOG_DEBUG "starting event handling")); m_primary->run(); @@ -982,11 +984,10 @@ void CServer::acceptClients(void*) // bind to the desired port. keep retrying if we can't bind // the address immediately. CStopwatch timer; - CNetworkAddress addr(50001 /* FIXME -- m_port */); for (;;) { try { log((CLOG_DEBUG1 "binding listen socket")); - listen->bind(addr); + listen->bind(m_config.getSynergyAddress()); break; } catch (XSocketAddressInUse&) { @@ -1166,11 +1167,10 @@ void CServer::acceptHTTPClients(void*) // bind to the desired port. keep retrying if we can't bind // the address immediately. CStopwatch timer; - CNetworkAddress addr(50002 /* FIXME -- m_httpPort */); for (;;) { try { - log((CLOG_DEBUG1 "binding listen socket")); - listen->bind(addr); + log((CLOG_DEBUG1 "binding HTTP listen socket")); + listen->bind(m_config.getHTTPAddress()); break; } catch (XSocketAddressInUse&) { diff --git a/server/CServer.h b/server/CServer.h index 37b1eb8f..ab4c92a2 100644 --- a/server/CServer.h +++ b/server/CServer.h @@ -6,6 +6,7 @@ #include "MouseTypes.h" #include "CConfig.h" #include "CClipboard.h" +#include "CNetworkAddress.h" #include "CCondVar.h" #include "CMutex.h" #include "CString.h" diff --git a/server/server.cpp b/server/server.cpp index 2a54cb03..c0c553d5 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -39,6 +39,8 @@ static bool s_install = false; static bool s_uninstall = false; static const char* s_configFile = NULL; static const char* s_logFilter = NULL; +static CNetworkAddress s_synergyAddress; +static CNetworkAddress s_httpAddress; static CConfig s_config; @@ -67,6 +69,7 @@ static void logLock(bool lock) static CServer* s_server = NULL; +#include static int realMain(CMutex* mutex) { // s_serverLock should have mutex locked on entry @@ -82,15 +85,27 @@ static int realMain(CMutex* mutex) bool locked = true; try { - // initialize network library - CNetwork::init(); - // if configuration has no screens then add this system // as the default if (s_config.begin() == s_config.end()) { s_config.addScreen("primary"); } + // set the contact address, if provided, in the config. + // otherwise, if the config doesn't have an address, use + // the default. + if (s_synergyAddress.isValid()) { + s_config.setSynergyAddress(s_synergyAddress); + } + else if (!s_config.getSynergyAddress().isValid()) { + s_config.setSynergyAddress(CNetworkAddress(kDefaultPort)); + } + + // set HTTP address is provided + if (s_httpAddress.isValid()) { + s_config.setHTTPAddress(s_httpAddress); + } + // create server s_server = new CServer(); @@ -195,6 +210,7 @@ static void help() "\n" "Start the synergy mouse/keyboard sharing server.\n" "\n" +" -a, --address
listen for clients on the given address.\n" " -c, --config use the named configuration file instead\n" " where ~ represents the user's home directory.\n" " -d, --debug filter out log messages with priorty below level.\n" @@ -212,6 +228,11 @@ static void help() "\n" "* marks defaults.\n" "\n" +"The argument for --address is of the form: [][:]. The\n" +"hostname must be the address or hostname of an interface on the system.\n" +"The default is to listen on all interfaces. The port overrides the\n" +"default port, %d.\n" +"\n" "If no configuration file pathname is provided then the first of the\n" "following to load sets the configuration:\n" " %s\n" @@ -222,6 +243,7 @@ static void help() "Where log messages go depends on the platform and whether or not the\n" "server is running as a "DAEMON".", pname, + kDefaultPort, platform.addPathComponent( platform.getUserDirectory(), CONFIG_NAME).c_str(), @@ -265,6 +287,32 @@ static void parse(int argc, const char** argv) s_logFilter = argv[++i]; } + else if (isArg(i, argc, argv, "-a", "--address", 1)) { + // save listen address + try { + s_synergyAddress = CNetworkAddress(argv[i + 1], kDefaultPort); + } + catch (XSocketAddress&) { + log((CLOG_PRINT "%s: invalid address for `%s'" BYE, + pname, argv[i], pname)); + bye(2); + } + ++i; + } + + else if (isArg(i, argc, argv, NULL, "--http", 1)) { + // save listen address + try { + s_httpAddress = CNetworkAddress(argv[i + 1], kDefaultPort + 1); + } + catch (XSocketAddress&) { + log((CLOG_PRINT "%s: invalid address for `%s'" BYE, + pname, argv[i], pname)); + bye(2); + } + ++i; + } + else if (isArg(i, argc, argv, "-c", "--config", 1)) { // save configuration file path s_configFile = argv[++i]; @@ -527,6 +575,9 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int) // get program name pname = platform.getBasename(__argv[0]); + // initialize network library + CNetwork::init(); + // parse command line without reporting errors but recording if // the app would've exited. this is too avoid showing a dialog // box if we're being started as a service because we shouldn't @@ -649,6 +700,9 @@ int main(int argc, char** argv) // get program name pname = platform.getBasename(argv[0]); + // initialize network library + CNetwork::init(); + // parse command line parse(argc, const_cast(argv)); diff --git a/synergy/ProtocolTypes.h b/synergy/ProtocolTypes.h index 32cd4e0b..b60fc831 100644 --- a/synergy/ProtocolTypes.h +++ b/synergy/ProtocolTypes.h @@ -7,6 +7,9 @@ static const SInt16 kProtocolMajorVersion = 0; static const SInt16 kProtocolMinorVersion = 1; +// contact port number +static const UInt16 kDefaultPort = 24800; + // // message codes (trailing NUL is not part of code). in comments, $n // refers to the n'th argument (counting from one). message codes are