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.
This commit is contained in:
crs 2002-06-09 16:53:25 +00:00
parent 8b2a282eb5
commit 555aa19eb2
14 changed files with 376 additions and 62 deletions

View File

@ -32,7 +32,7 @@ static bool s_daemon = true;
static bool s_install = false; static bool s_install = false;
static bool s_uninstall = false; static bool s_uninstall = false;
static const char* s_logFilter = NULL; 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 int realMain(CMutex* mutex)
{ {
static const UInt16 port = 50001; // FIXME
try { try {
// initialize threading library // initialize threading library
CThread::init(); CThread::init();
@ -75,11 +73,7 @@ static int realMain(CMutex* mutex)
bool locked = true; bool locked = true;
try { try {
// initialize network library
CNetwork::init();
// create client // create client
CNetworkAddress addr(s_serverName, port);
s_client = new CClient("secondary"); // FIXME s_client = new CClient("secondary"); // FIXME
// run client // run client
@ -87,7 +81,7 @@ static int realMain(CMutex* mutex)
mutex->unlock(); mutex->unlock();
} }
locked = false; locked = false;
s_client->run(addr); s_client->run(s_serverAddress);
locked = true; locked = true;
if (mutex != NULL) { if (mutex != NULL) {
mutex->lock(); mutex->lock();
@ -194,9 +188,13 @@ static void help()
"\n" "\n"
"* marks defaults.\n" "* marks defaults.\n"
"\n" "\n"
"The server address is of the form: [<hostname>][:<port>]. 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" "Where log messages go depends on the platform and whether or not the\n"
"client is running as a "DAEMON".", "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)); pname, argv[i], pname));
bye(2); 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 // increase default filter level for daemon. the user must
@ -445,6 +452,9 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
// get program name // get program name
pname = platform.getBasename(__argv[0]); pname = platform.getBasename(__argv[0]);
// initialize network library
CNetwork::init();
// parse command line without reporting errors but recording if // parse command line without reporting errors but recording if
// the app would've exited. this is too avoid showing a dialog // 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 // 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 += s_logFilter;
} }
commandLine += " "; commandLine += " ";
commandLine += s_serverName; commandLine += s_serverAddress.getHostname().c_str();
// install // install
if (!platform.installDaemon(DAEMON_NAME, if (!platform.installDaemon(DAEMON_NAME,
@ -560,6 +570,9 @@ int main(int argc, char** argv)
// get program name // get program name
pname = platform.getBasename(argv[0]); pname = platform.getBasename(argv[0]);
// initialize network library
CNetwork::init();
// parse command line // parse command line
parse(argc, const_cast<const char**>(argv)); parse(argc, const_cast<const char**>(argv));

View File

@ -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::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::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); 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); unsigned long (PASCAL FAR *CNetwork::inet_addr)(const char FAR * cp);
char FAR * (PASCAL FAR *CNetwork::inet_ntoa)(struct in_addr in); char FAR * (PASCAL FAR *CNetwork::inet_ntoa)(struct in_addr in);
int (PASCAL FAR *CNetwork::listen)(CNetwork::Socket s, int backlog); 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::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::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); 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) #define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name)
void CNetwork::init2(HMODULE module) 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(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(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(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_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(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog)); 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(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(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)); 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 #define setfunc(var, name, type) var = (type)::name
static UInt32 myhtonl(UInt32 v) UInt32 CNetwork::swaphtonl(UInt32 v)
{ {
return htonl(v); return htonl(v);
} }
static UInt16 myhtons(UInt16 v) UInt16 CNetwork::swaphtons(UInt16 v)
{ {
return htons(v); return htons(v);
} }
static UInt32 myntohl(UInt32 v) UInt32 CNetwork::swapntohl(UInt32 v)
{ {
return ntohl(v); return ntohl(v);
} }
static UInt16 myntohs(UInt16 v) UInt16 CNetwork::swapntohs(UInt16 v)
{ {
return ntohs(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(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(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(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_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(inet_ntoa, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
setfunc(listen, listen, int (PASCAL FAR *)(Socket s, int backlog)); 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(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(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)); setfunc(recv, recv, ssize_t (PASCAL FAR *)(Socket s, void FAR * buf, size_t len, int flags));

View File

@ -69,6 +69,12 @@ public:
static void init(); static void init();
static void cleanup(); 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 // constants
static const int Error; static const int Error;
@ -100,7 +106,7 @@ public:
kHNone = 0 kHNone = 0
}; };
// socket interface // socket interface (only available after init())
static Socket (PASCAL FAR *accept)(Socket s, Address FAR *addr, AddressLength FAR *addrlen); 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); 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 *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 *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 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 unsigned long (PASCAL FAR *inet_addr)(const char FAR * cp);
static char FAR * (PASCAL FAR *inet_ntoa)(struct in_addr in); static char FAR * (PASCAL FAR *inet_ntoa)(struct in_addr in);
static int (PASCAL FAR *listen)(Socket s, int backlog); 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 *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 *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); static ssize_t (PASCAL FAR *recvfrom)(Socket s, void FAR * buf, size_t len, int flags, Address FAR *from, AddressLength FAR * fromlen);

View File

@ -1,26 +1,102 @@
#include "CNetworkAddress.h" #include "CNetworkAddress.h"
#include "CString.h"
#include <stdlib.h>
// //
// CNetworkAddress // CNetworkAddress
// //
CNetworkAddress::CNetworkAddress(UInt16 port) CNetworkAddress::CNetworkAddress() : m_port(0)
{ {
if (port == 0) // note -- make no calls to CNetwork socket interface here;
throw XSocketAddress(XSocketAddress::kBadPort, CString(), port); // we're often called prior to CNetwork::init().
struct sockaddr_in* inetAddress = reinterpret_cast<struct sockaddr_in*>(&m_address); struct sockaddr_in* inetAddress = reinterpret_cast<
struct sockaddr_in*>(&m_address);
inetAddress->sin_family = AF_INET; 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; inetAddress->sin_addr.s_addr = INADDR_ANY;
memset(inetAddress->sin_zero, 0, sizeof(inetAddress->sin_zero)); 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) if (port == 0) {
throw XSocketAddress(XSocketAddress::kBadPort, hostname, port); 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<UInt16>(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()); struct hostent* hent = CNetwork::gethostbyname(hostname.c_str());
if (hent == NULL) { if (hent == NULL) {
switch (CNetwork::gethosterror()) { switch (CNetwork::gethosterror()) {
@ -37,7 +113,8 @@ CNetworkAddress::CNetworkAddress(const CString& hostname, UInt16 port)
} }
} }
struct sockaddr_in* inetAddress = reinterpret_cast<struct sockaddr_in*>(&m_address); struct sockaddr_in* inetAddress = reinterpret_cast<
struct sockaddr_in*>(&m_address);
inetAddress->sin_family = hent->h_addrtype; inetAddress->sin_family = hent->h_addrtype;
inetAddress->sin_port = CNetwork::swaphtons(port); inetAddress->sin_port = CNetwork::swaphtons(port);
memcpy(&inetAddress->sin_addr, hent->h_addr_list[0], hent->h_length); memcpy(&inetAddress->sin_addr, hent->h_addr_list[0], hent->h_length);
@ -49,6 +126,11 @@ CNetworkAddress::~CNetworkAddress()
// do nothing // do nothing
} }
bool CNetworkAddress::isValid() const
{
return (m_port != 0);
}
const CNetwork::Address* CNetworkAddress::getAddress() const const CNetwork::Address* CNetworkAddress::getAddress() const
{ {
return &m_address; return &m_address;
@ -58,3 +140,13 @@ CNetwork::AddressLength CNetworkAddress::getAddressLength() const
{ {
return sizeof(m_address); return sizeof(m_address);
} }
CString CNetworkAddress::getHostname() const
{
return m_hostname;
}
UInt16 CNetworkAddress::getPort() const
{
return m_port;
}

View File

@ -1,27 +1,48 @@
#ifndef CNETWORKADDRESS_H #ifndef CNETWORKADDRESS_H
#define CNETWORKADDRESS_H #define CNETWORKADDRESS_H
#include "BasicTypes.h"
#include "CNetwork.h" #include "CNetwork.h"
#include "XSocket.h" #include "XSocket.h"
#include "CString.h"
class CString; #include "BasicTypes.h"
class CNetworkAddress { class CNetworkAddress {
public: public:
// invalid address
CNetworkAddress();
// wildcard address and given port. port must not be zero.
CNetworkAddress(UInt16 port); 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(const CString& hostname, UInt16 port);
~CNetworkAddress(); ~CNetworkAddress();
// manipulators // manipulators
// accessors // accessors
// returns true if this is not the invalid address
bool isValid() const;
// get the address
const CNetwork::Address* getAddress() const; const CNetwork::Address* getAddress() const;
CNetwork::AddressLength getAddressLength() const; CNetwork::AddressLength getAddressLength() const;
// get the hostname and port (as provided in the c'tor)
CString getHostname() const;
UInt16 getPort() const;
private: private:
CNetwork::Address m_address; CNetwork::Address m_address;
CString m_hostname;
UInt16 m_port;
}; };
#endif #endif

View File

@ -5,7 +5,7 @@
// //
XSocketAddress::XSocketAddress(Error error, XSocketAddress::XSocketAddress(Error error,
const CString& hostname, SInt16 port) throw() : const CString& hostname, UInt16 port) throw() :
m_error(error), m_error(error),
m_hostname(hostname), m_hostname(hostname),
m_port(port) m_port(port)
@ -23,7 +23,7 @@ CString XSocketAddress::getHostname() const throw()
return m_hostname; return m_hostname;
} }
SInt16 XSocketAddress::getPort() const throw() UInt16 XSocketAddress::getPort() const throw()
{ {
return m_port; return m_port;
} }

View File

@ -11,13 +11,13 @@ class XSocketAddress : public XSocket {
public: public:
enum Error { kUnknown, kNotFound, kNoAddress, kBadPort }; enum Error { kUnknown, kNotFound, kNoAddress, kBadPort };
XSocketAddress(Error, const CString& hostname, SInt16 port) throw(); XSocketAddress(Error, const CString& hostname, UInt16 port) throw();
// accessors // accessors
virtual Error getError() const throw(); virtual Error getError() const throw();
virtual CString getHostname() const throw(); virtual CString getHostname() const throw();
virtual SInt16 getPort() const throw(); virtual UInt16 getPort() const throw();
protected: protected:
// XBase overrides // XBase overrides
@ -26,7 +26,7 @@ protected:
private: private:
Error m_error; Error m_error;
CString m_hostname; CString m_hostname;
SInt16 m_port; UInt16 m_port;
}; };
class XSocketErrno : public XSocket, public MXErrno { class XSocketErrno : public XSocket, public MXErrno {

View File

@ -1,4 +1,5 @@
#include "CConfig.h" #include "CConfig.h"
#include "ProtocolTypes.h"
#include "stdistream.h" #include "stdistream.h"
#include "stdostream.h" #include "stdostream.h"
#include <assert.h> #include <assert.h>
@ -156,6 +157,16 @@ bool CConfig::disconnect(const CString& srcName,
return true; 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 bool CConfig::isValidScreenName(const CString& name) const
{ {
// name is valid if matches validname // name is valid if matches validname
@ -245,6 +256,16 @@ CString CConfig::getNeighbor(const CString& srcName,
srcSide - kFirstDirection]); srcSide - kFirstDirection]);
} }
const CNetworkAddress& CConfig::getSynergyAddress() const
{
return m_synergyAddress;
}
const CNetworkAddress& CConfig::getHTTPAddress() const
{
return m_httpAddress;
}
const char* CConfig::dirName(EDirection dir) const char* CConfig::dirName(EDirection dir)
{ {
static const char* s_name[] = { "left", "right", "top", "bottom" }; 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) void CConfig::readSection(std::istream& s)
{ {
static const char s_section[] = "section:"; static const char s_section[] = "section:";
static const char s_network[] = "network";
static const char s_screens[] = "screens"; static const char s_screens[] = "screens";
static const char s_links[] = "links"; static const char s_links[] = "links";
static const char s_aliases[] = "aliases"; static const char s_aliases[] = "aliases";
@ -304,7 +326,10 @@ void CConfig::readSection(std::istream& s)
} }
// read section // read section
if (name == s_screens) { if (name == s_network) {
readSectionNetwork(s);
}
else if (name == s_screens) {
readSectionScreens(s); readSectionScreens(s);
} }
else if (name == s_links) { 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: `<name>=<value>'
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) void CConfig::readSectionScreens(std::istream& s)
{ {
CString line; CString line;
@ -493,6 +573,18 @@ std::istream& operator>>(std::istream& s, CConfig& config)
std::ostream& operator<<(std::ostream& s, const 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 // screens section
s << "section: screens" << std::endl; s << "section: screens" << std::endl;
for (CConfig::const_iterator screen = config.begin(); for (CConfig::const_iterator screen = config.begin();

View File

@ -3,6 +3,7 @@
#include "BasicTypes.h" #include "BasicTypes.h"
#include "CString.h" #include "CString.h"
#include "CNetworkAddress.h"
#include "XBase.h" #include "XBase.h"
#include <iosfwd> #include <iosfwd>
#include "stdmap.h" #include "stdmap.h"
@ -96,6 +97,11 @@ public:
bool disconnect(const CString& srcName, bool disconnect(const CString& srcName,
EDirection srcSide); EDirection srcSide);
// set the synergy and http listen addresses. there are no
// default addresses.
void setSynergyAddress(const CNetworkAddress&);
void setHTTPAddress(const CNetworkAddress&);
// accessors // accessors
// returns true iff the given name is a valid screen name. // returns true iff the given name is a valid screen name.
@ -120,6 +126,10 @@ public:
// screen name. // screen name.
CString getNeighbor(const CString&, EDirection) const; 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 // read/write a configuration. operator>> will throw XConfigRead
// on error. // on error.
friend std::istream& operator>>(std::istream&, CConfig&); friend std::istream& operator>>(std::istream&, CConfig&);
@ -131,6 +141,7 @@ public:
private: private:
static bool readLine(std::istream&, CString&); static bool readLine(std::istream&, CString&);
void readSection(std::istream&); void readSection(std::istream&);
void readSectionNetwork(std::istream&);
void readSectionScreens(std::istream&); void readSectionScreens(std::istream&);
void readSectionLinks(std::istream&); void readSectionLinks(std::istream&);
void readSectionAliases(std::istream&); void readSectionAliases(std::istream&);
@ -140,6 +151,8 @@ private:
CCellMap m_map; CCellMap m_map;
CNameMap m_nameToCanonicalName; CNameMap m_nameToCanonicalName;
CNetworkAddress m_synergyAddress;
CNetworkAddress m_httpAddress;
}; };
class XConfigRead : public XBase { class XConfigRead : public XBase {

View File

@ -308,6 +308,7 @@ void CHTTPServer::doProcessPostEditMap(
// convert temporary screen map into a regular map // convert temporary screen map into a regular map
CConfig config; CConfig config;
m_server->getConfig(&config);
screens.convertTo(config); screens.convertTo(config);
// set new screen map on server // set new screen map on server
@ -719,6 +720,8 @@ bool CHTTPServer::CScreenArray::convertFrom(
void CHTTPServer::CScreenArray::convertTo( void CHTTPServer::CScreenArray::convertTo(
CConfig& config) const CConfig& config) const
{ {
config.removeAllScreens();
// add screens and find smallest box containing all screens // add screens and find smallest box containing all screens
SInt32 x0 = m_w, x1 = 0, y0 = m_h, y1 = 0; SInt32 x0 = m_w, x1 = 0, y0 = m_h, y1 = 0;
for (SInt32 y = 0; y < m_h; ++y) { for (SInt32 y = 0; y < m_h; ++y) {

View File

@ -83,13 +83,15 @@ void CServer::run()
} }
} }
// start listening for HTTP requests
m_httpServer = new CHTTPServer(this);
CThread(new TMethodJob<CServer>(this, &CServer::acceptHTTPClients));
// start listening for new clients // start listening for new clients
CThread(new TMethodJob<CServer>(this, &CServer::acceptClients)); CThread(new TMethodJob<CServer>(this, &CServer::acceptClients));
// start listening for HTTP requests
if (m_config.getHTTPAddress().isValid()) {
m_httpServer = new CHTTPServer(this);
CThread(new TMethodJob<CServer>(this, &CServer::acceptHTTPClients));
}
// handle events // handle events
log((CLOG_DEBUG "starting event handling")); log((CLOG_DEBUG "starting event handling"));
m_primary->run(); m_primary->run();
@ -982,11 +984,10 @@ void CServer::acceptClients(void*)
// 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.
CStopwatch timer; CStopwatch timer;
CNetworkAddress addr(50001 /* FIXME -- m_port */);
for (;;) { for (;;) {
try { try {
log((CLOG_DEBUG1 "binding listen socket")); log((CLOG_DEBUG1 "binding listen socket"));
listen->bind(addr); listen->bind(m_config.getSynergyAddress());
break; break;
} }
catch (XSocketAddressInUse&) { catch (XSocketAddressInUse&) {
@ -1166,11 +1167,10 @@ void CServer::acceptHTTPClients(void*)
// 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.
CStopwatch timer; CStopwatch timer;
CNetworkAddress addr(50002 /* FIXME -- m_httpPort */);
for (;;) { for (;;) {
try { try {
log((CLOG_DEBUG1 "binding listen socket")); log((CLOG_DEBUG1 "binding HTTP listen socket"));
listen->bind(addr); listen->bind(m_config.getHTTPAddress());
break; break;
} }
catch (XSocketAddressInUse&) { catch (XSocketAddressInUse&) {

View File

@ -6,6 +6,7 @@
#include "MouseTypes.h" #include "MouseTypes.h"
#include "CConfig.h" #include "CConfig.h"
#include "CClipboard.h" #include "CClipboard.h"
#include "CNetworkAddress.h"
#include "CCondVar.h" #include "CCondVar.h"
#include "CMutex.h" #include "CMutex.h"
#include "CString.h" #include "CString.h"

View File

@ -39,6 +39,8 @@ static bool s_install = false;
static bool s_uninstall = false; static bool s_uninstall = false;
static const char* s_configFile = NULL; static const char* s_configFile = NULL;
static const char* s_logFilter = NULL; static const char* s_logFilter = NULL;
static CNetworkAddress s_synergyAddress;
static CNetworkAddress s_httpAddress;
static CConfig s_config; static CConfig s_config;
@ -67,6 +69,7 @@ static void logLock(bool lock)
static CServer* s_server = NULL; static CServer* s_server = NULL;
#include <signal.h>
static int realMain(CMutex* mutex) static int realMain(CMutex* mutex)
{ {
// s_serverLock should have mutex locked on entry // s_serverLock should have mutex locked on entry
@ -82,15 +85,27 @@ static int realMain(CMutex* mutex)
bool locked = true; bool locked = true;
try { try {
// initialize network library
CNetwork::init();
// if configuration has no screens then add this system // if configuration has no screens then add this system
// as the default // as the default
if (s_config.begin() == s_config.end()) { if (s_config.begin() == s_config.end()) {
s_config.addScreen("primary"); 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 // create server
s_server = new CServer(); s_server = new CServer();
@ -195,6 +210,7 @@ static void help()
"\n" "\n"
"Start the synergy mouse/keyboard sharing server.\n" "Start the synergy mouse/keyboard sharing server.\n"
"\n" "\n"
" -a, --address <address> listen for clients on the given address.\n"
" -c, --config <pathname> use the named configuration file instead\n" " -c, --config <pathname> use the named configuration file instead\n"
" where ~ represents the user's home directory.\n" " where ~ represents the user's home directory.\n"
" -d, --debug <level> filter out log messages with priorty below level.\n" " -d, --debug <level> filter out log messages with priorty below level.\n"
@ -212,6 +228,11 @@ static void help()
"\n" "\n"
"* marks defaults.\n" "* marks defaults.\n"
"\n" "\n"
"The argument for --address is of the form: [<hostname>][:<port>]. 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" "If no configuration file pathname is provided then the first of the\n"
"following to load sets the configuration:\n" "following to load sets the configuration:\n"
" %s\n" " %s\n"
@ -222,6 +243,7 @@ static void help()
"Where log messages go depends on the platform and whether or not the\n" "Where log messages go depends on the platform and whether or not the\n"
"server is running as a "DAEMON".", "server is running as a "DAEMON".",
pname, pname,
kDefaultPort,
platform.addPathComponent( platform.addPathComponent(
platform.getUserDirectory(), platform.getUserDirectory(),
CONFIG_NAME).c_str(), CONFIG_NAME).c_str(),
@ -265,6 +287,32 @@ static void parse(int argc, const char** argv)
s_logFilter = argv[++i]; 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)) { else if (isArg(i, argc, argv, "-c", "--config", 1)) {
// save configuration file path // save configuration file path
s_configFile = argv[++i]; s_configFile = argv[++i];
@ -527,6 +575,9 @@ int WINAPI WinMain(HINSTANCE instance, HINSTANCE, LPSTR, int)
// get program name // get program name
pname = platform.getBasename(__argv[0]); pname = platform.getBasename(__argv[0]);
// initialize network library
CNetwork::init();
// parse command line without reporting errors but recording if // parse command line without reporting errors but recording if
// the app would've exited. this is too avoid showing a dialog // 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 // 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 // get program name
pname = platform.getBasename(argv[0]); pname = platform.getBasename(argv[0]);
// initialize network library
CNetwork::init();
// parse command line // parse command line
parse(argc, const_cast<const char**>(argv)); parse(argc, const_cast<const char**>(argv));

View File

@ -7,6 +7,9 @@
static const SInt16 kProtocolMajorVersion = 0; static const SInt16 kProtocolMajorVersion = 0;
static const SInt16 kProtocolMinorVersion = 1; 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 // 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