Adapted and applied patch by Brent Priddy for re-resolving the server
hostname on each connection. This allows the client to startup without being able to resolve the server's hostname. It also lets it handle changes in the server's address, a typical scenario when the client is a laptop moving between networks.
This commit is contained in:
parent
34c2be00e5
commit
3d961e4767
|
@ -694,12 +694,19 @@ parse(int argc, const char* const* argv)
|
||||||
// save server address
|
// save server address
|
||||||
try {
|
try {
|
||||||
*ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
|
*ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
|
||||||
|
ARG->m_serverAddress->resolve();
|
||||||
}
|
}
|
||||||
catch (XSocketAddress& e) {
|
catch (XSocketAddress& e) {
|
||||||
|
// allow an address that we can't look up if we're restartable.
|
||||||
|
// we'll try to resolve the address each time we connect to the
|
||||||
|
// server. a bad port will never get better. patch by Brent
|
||||||
|
// Priddy.
|
||||||
|
if (!ARG->m_restartable || e.getError() == XSocketAddress::kBadPort) {
|
||||||
LOG((CLOG_PRINT "%s: %s" BYE,
|
LOG((CLOG_PRINT "%s: %s" BYE,
|
||||||
ARG->m_pname, e.what(), ARG->m_pname));
|
ARG->m_pname, e.what(), ARG->m_pname));
|
||||||
bye(kExitFailed);
|
bye(kExitFailed);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// increase default filter level for daemon. the user must
|
// increase default filter level for daemon. the user must
|
||||||
// explicitly request another level for a daemon.
|
// explicitly request another level for a daemon.
|
||||||
|
|
|
@ -744,6 +744,7 @@ parse(int argc, const char* const* argv)
|
||||||
try {
|
try {
|
||||||
*ARG->m_synergyAddress = CNetworkAddress(argv[i + 1],
|
*ARG->m_synergyAddress = CNetworkAddress(argv[i + 1],
|
||||||
kDefaultPort);
|
kDefaultPort);
|
||||||
|
ARG->m_synergyAddress->resolve();
|
||||||
}
|
}
|
||||||
catch (XSocketAddress& e) {
|
catch (XSocketAddress& e) {
|
||||||
LOG((CLOG_PRINT "%s: %s" BYE,
|
LOG((CLOG_PRINT "%s: %s" BYE,
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
<td><a href="mailto:vttom@users.sourceforge.net">Tom Chadwick</a></td>
|
<td><a href="mailto:vttom@users.sourceforge.net">Tom Chadwick</a></td>
|
||||||
<td>PageUp/PageDown on X servers without mouse wheel support</td>
|
<td>PageUp/PageDown on X servers without mouse wheel support</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><a href="mailto:toopriddy@users.sourceforge.net">Brent Priddy</a></td>
|
||||||
|
<td>Re-resolving server hostname on each connection</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</p>
|
</p>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -74,6 +74,14 @@ CClient::connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
// resolve the server hostname. do this every time we connect
|
||||||
|
// in case we couldn't resolve the address earlier or the address
|
||||||
|
// has changed (which can happen frequently if this is a laptop
|
||||||
|
// being shuttled between various networks). patch by Brent
|
||||||
|
// Priddy.
|
||||||
|
m_serverAddress.resolve();
|
||||||
|
|
||||||
|
// create the socket
|
||||||
IDataSocket* socket = m_socketFactory->create();
|
IDataSocket* socket = m_socketFactory->create();
|
||||||
|
|
||||||
// filter socket messages, including a packetizing filter
|
// filter socket messages, including a packetizing filter
|
||||||
|
|
|
@ -22,54 +22,56 @@
|
||||||
// CNetworkAddress
|
// CNetworkAddress
|
||||||
//
|
//
|
||||||
|
|
||||||
|
// name re-resolution adapted from a patch by Brent Priddy.
|
||||||
|
|
||||||
CNetworkAddress::CNetworkAddress() :
|
CNetworkAddress::CNetworkAddress() :
|
||||||
m_address(NULL)
|
m_address(NULL),
|
||||||
|
m_hostname(),
|
||||||
|
m_port(0)
|
||||||
{
|
{
|
||||||
// note -- make no calls to CNetwork socket interface here;
|
// note -- make no calls to CNetwork socket interface here;
|
||||||
// we're often called prior to CNetwork::init().
|
// we're often called prior to CNetwork::init().
|
||||||
}
|
}
|
||||||
|
|
||||||
CNetworkAddress::CNetworkAddress(int port)
|
CNetworkAddress::CNetworkAddress(int port) :
|
||||||
|
m_address(NULL),
|
||||||
|
m_hostname(),
|
||||||
|
m_port(port)
|
||||||
{
|
{
|
||||||
if (port == 0) {
|
checkPort();
|
||||||
throw XSocketAddress(XSocketAddress::kBadPort, "", port);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
|
m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
|
||||||
ARCH->setAddrPort(m_address, port);
|
ARCH->setAddrPort(m_address, m_port);
|
||||||
}
|
}
|
||||||
|
|
||||||
CNetworkAddress::CNetworkAddress(const CNetworkAddress& addr) :
|
CNetworkAddress::CNetworkAddress(const CNetworkAddress& addr) :
|
||||||
m_address(ARCH->copyAddr(addr.m_address)),
|
m_address(addr.m_address != NULL ? ARCH->copyAddr(addr.m_address) : NULL),
|
||||||
m_hostname(addr.m_hostname)
|
m_hostname(addr.m_hostname),
|
||||||
|
m_port(addr.m_port)
|
||||||
{
|
{
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
CNetworkAddress::CNetworkAddress(const CString& hostname_, int port) :
|
CNetworkAddress::CNetworkAddress(const CString& hostname, int port) :
|
||||||
m_hostname(hostname_)
|
m_address(NULL),
|
||||||
|
m_hostname(hostname),
|
||||||
|
m_port(port)
|
||||||
{
|
{
|
||||||
if (port == 0) {
|
|
||||||
throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for port suffix
|
// check for port suffix
|
||||||
CString hostname(m_hostname);
|
CString::size_type i = m_hostname.rfind(':');
|
||||||
CString::size_type i = hostname.rfind(':');
|
if (i != CString::npos && i + 1 < m_hostname.size()) {
|
||||||
if (i != CString::npos && i + 1 < hostname.size()) {
|
|
||||||
// found a colon. see if it looks like an IPv6 address.
|
// found a colon. see if it looks like an IPv6 address.
|
||||||
bool colonNotation = false;
|
bool colonNotation = false;
|
||||||
bool dotNotation = false;
|
bool dotNotation = false;
|
||||||
bool doubleColon = false;
|
bool doubleColon = false;
|
||||||
for (CString::size_type j = 0; j < i; ++j) {
|
for (CString::size_type j = 0; j < i; ++j) {
|
||||||
if (hostname[j] == ':') {
|
if (m_hostname[j] == ':') {
|
||||||
colonNotation = true;
|
colonNotation = true;
|
||||||
dotNotation = false;
|
dotNotation = false;
|
||||||
if (hostname[j + 1] == ':') {
|
if (m_hostname[j + 1] == ':') {
|
||||||
doubleColon = true;
|
doubleColon = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hostname[j] == '.' && colonNotation) {
|
else if (m_hostname[j] == '.' && colonNotation) {
|
||||||
dotNotation = true;
|
dotNotation = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,46 +82,25 @@ CNetworkAddress::CNetworkAddress(const CString& hostname_, int port) :
|
||||||
// the user can replace the double colon with zeros to
|
// the user can replace the double colon with zeros to
|
||||||
// disambiguate.
|
// disambiguate.
|
||||||
if ((!doubleColon || dotNotation) || !colonNotation) {
|
if ((!doubleColon || dotNotation) || !colonNotation) {
|
||||||
|
// parse port from hostname
|
||||||
char* end;
|
char* end;
|
||||||
long suffixPort = strtol(hostname.c_str() + i + 1, &end, 10);
|
const char* chostname = m_hostname.c_str();
|
||||||
if (end == hostname.c_str() + i + 1 || *end != '\0' ||
|
long suffixPort = strtol(chostname + i + 1, &end, 10);
|
||||||
suffixPort <= 0 || suffixPort > 65535) {
|
if (end == chostname + i + 1 || *end != '\0') {
|
||||||
// bogus port
|
|
||||||
throw XSocketAddress(XSocketAddress::kBadPort,
|
throw XSocketAddress(XSocketAddress::kBadPort,
|
||||||
m_hostname, port);
|
m_hostname, m_port);
|
||||||
}
|
|
||||||
else {
|
|
||||||
// good port
|
|
||||||
port = static_cast<int>(suffixPort);
|
|
||||||
hostname.erase(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// trim port from hostname
|
||||||
|
m_hostname.erase(i);
|
||||||
|
|
||||||
|
// save port
|
||||||
|
m_port = static_cast<int>(suffixPort);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// if hostname is empty then use wildcard address
|
// check port number
|
||||||
if (hostname.empty()) {
|
checkPort();
|
||||||
m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
|
|
||||||
ARCH->setAddrPort(m_address, port);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// look up name
|
|
||||||
try {
|
|
||||||
m_address = ARCH->nameToAddr(hostname);
|
|
||||||
ARCH->setAddrPort(m_address, port);
|
|
||||||
}
|
|
||||||
catch (XArchNetworkNameUnknown&) {
|
|
||||||
throw XSocketAddress(XSocketAddress::kNotFound, hostname, port);
|
|
||||||
}
|
|
||||||
catch (XArchNetworkNameNoAddress&) {
|
|
||||||
throw XSocketAddress(XSocketAddress::kNoAddress, hostname, port);
|
|
||||||
}
|
|
||||||
catch (XArchNetworkNameUnsupported&) {
|
|
||||||
throw XSocketAddress(XSocketAddress::kUnsupported, hostname, port);
|
|
||||||
}
|
|
||||||
catch (XArchNetworkName&) {
|
|
||||||
throw XSocketAddress(XSocketAddress::kUnknown, hostname, port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CNetworkAddress::~CNetworkAddress()
|
CNetworkAddress::~CNetworkAddress()
|
||||||
|
@ -139,11 +120,48 @@ CNetworkAddress::operator=(const CNetworkAddress& addr)
|
||||||
if (m_address != NULL) {
|
if (m_address != NULL) {
|
||||||
ARCH->closeAddr(m_address);
|
ARCH->closeAddr(m_address);
|
||||||
}
|
}
|
||||||
m_hostname = addr.m_hostname;
|
|
||||||
m_address = newAddr;
|
m_address = newAddr;
|
||||||
|
m_hostname = addr.m_hostname;
|
||||||
|
m_port = addr.m_port;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CNetworkAddress::resolve()
|
||||||
|
{
|
||||||
|
// discard previous address
|
||||||
|
if (m_address != NULL) {
|
||||||
|
ARCH->closeAddr(m_address);
|
||||||
|
m_address = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// if hostname is empty then use wildcard address otherwise look
|
||||||
|
// up the name.
|
||||||
|
if (m_hostname.empty()) {
|
||||||
|
m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_address = ARCH->nameToAddr(m_hostname);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (XArchNetworkNameUnknown&) {
|
||||||
|
throw XSocketAddress(XSocketAddress::kNotFound, m_hostname, m_port);
|
||||||
|
}
|
||||||
|
catch (XArchNetworkNameNoAddress&) {
|
||||||
|
throw XSocketAddress(XSocketAddress::kNoAddress, m_hostname, m_port);
|
||||||
|
}
|
||||||
|
catch (XArchNetworkNameUnsupported&) {
|
||||||
|
throw XSocketAddress(XSocketAddress::kUnsupported, m_hostname, m_port);
|
||||||
|
}
|
||||||
|
catch (XArchNetworkName&) {
|
||||||
|
throw XSocketAddress(XSocketAddress::kUnknown, m_hostname, m_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set port in address
|
||||||
|
ARCH->setAddrPort(m_address, m_port);
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
CNetworkAddress::operator==(const CNetworkAddress& addr) const
|
CNetworkAddress::operator==(const CNetworkAddress& addr) const
|
||||||
{
|
{
|
||||||
|
@ -171,7 +189,7 @@ CNetworkAddress::getAddress() const
|
||||||
int
|
int
|
||||||
CNetworkAddress::getPort() const
|
CNetworkAddress::getPort() const
|
||||||
{
|
{
|
||||||
return (m_address == NULL) ? 0 : ARCH->getAddrPort(m_address);
|
return m_port;
|
||||||
}
|
}
|
||||||
|
|
||||||
CString
|
CString
|
||||||
|
@ -179,3 +197,12 @@ CNetworkAddress::getHostname() const
|
||||||
{
|
{
|
||||||
return m_hostname;
|
return m_hostname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
CNetworkAddress::checkPort()
|
||||||
|
{
|
||||||
|
// check port number
|
||||||
|
if (m_port <= 0 || m_port > 65535) {
|
||||||
|
throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, m_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -39,10 +39,12 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Construct the network address for the given \c hostname and \c port.
|
Construct the network address for the given \c hostname and \c port.
|
||||||
If \c hostname can be parsed as a numerical address then that's how
|
If \c hostname can be parsed as a numerical address then that's how
|
||||||
it's used, otherwise the host name is looked up. If the lookup fails
|
it's used, otherwise it's used as a host name. If \c hostname ends
|
||||||
then this throws XSocketAddress. If \c hostname ends in ":[0-9]+" then
|
in ":[0-9]+" then that suffix is extracted and used as the port,
|
||||||
that suffix is extracted and used as the port, overridding the port
|
overridding the port parameter. The resulting port must be a valid
|
||||||
parameter. Neither the extracted port or \c port may be zero.
|
port number (zero is not a valid port number) otherwise \c XSocketAddress
|
||||||
|
is thrown with an error of \c XSocketAddress::kBadPort. The hostname
|
||||||
|
is not resolved by the c'tor; use \c resolve to do that.
|
||||||
*/
|
*/
|
||||||
CNetworkAddress(const CString& hostname, int port);
|
CNetworkAddress(const CString& hostname, int port);
|
||||||
|
|
||||||
|
@ -52,6 +54,19 @@ public:
|
||||||
|
|
||||||
CNetworkAddress& operator=(const CNetworkAddress&);
|
CNetworkAddress& operator=(const CNetworkAddress&);
|
||||||
|
|
||||||
|
//! @name manipulators
|
||||||
|
//@{
|
||||||
|
|
||||||
|
//! Resolve address
|
||||||
|
/*!
|
||||||
|
Resolves the hostname to an address. This can be done any number of
|
||||||
|
times and is done automatically by the c'tor taking a hostname.
|
||||||
|
Throws XSocketAddress if resolution is unsuccessful, after which
|
||||||
|
\c isValid returns false until the next call to this method.
|
||||||
|
*/
|
||||||
|
void resolve();
|
||||||
|
|
||||||
|
//@}
|
||||||
//! @name accessors
|
//! @name accessors
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
@ -59,13 +74,13 @@ public:
|
||||||
/*!
|
/*!
|
||||||
Returns true if this address is equal to \p address.
|
Returns true if this address is equal to \p address.
|
||||||
*/
|
*/
|
||||||
bool operator==(const CNetworkAddress&) const;
|
bool operator==(const CNetworkAddress& address) const;
|
||||||
|
|
||||||
//! Check address inequality
|
//! Check address inequality
|
||||||
/*!
|
/*!
|
||||||
Returns true if this address is not equal to \p address.
|
Returns true if this address is not equal to \p address.
|
||||||
*/
|
*/
|
||||||
bool operator!=(const CNetworkAddress&) const;
|
bool operator!=(const CNetworkAddress& address) const;
|
||||||
|
|
||||||
//! Check address validity
|
//! Check address validity
|
||||||
/*!
|
/*!
|
||||||
|
@ -89,15 +104,19 @@ public:
|
||||||
|
|
||||||
//! Get hostname
|
//! Get hostname
|
||||||
/*!
|
/*!
|
||||||
Returns the hostname passed to the c'tor sans the port suffix.
|
Returns the hostname passed to the c'tor sans any port suffix.
|
||||||
*/
|
*/
|
||||||
CString getHostname() const;
|
CString getHostname() const;
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void checkPort();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CArchNetAddress m_address;
|
CArchNetAddress m_address;
|
||||||
CString m_hostname;
|
CString m_hostname;
|
||||||
|
int m_port;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -780,6 +780,7 @@ CConfig::readSectionOptions(std::istream& s)
|
||||||
if (name == "address") {
|
if (name == "address") {
|
||||||
try {
|
try {
|
||||||
m_synergyAddress = CNetworkAddress(value, kDefaultPort);
|
m_synergyAddress = CNetworkAddress(value, kDefaultPort);
|
||||||
|
m_synergyAddress.resolve();
|
||||||
}
|
}
|
||||||
catch (XSocketAddress& e) {
|
catch (XSocketAddress& e) {
|
||||||
throw XConfigRead(CString("invalid address argument: ") +
|
throw XConfigRead(CString("invalid address argument: ") +
|
||||||
|
|
Loading…
Reference in New Issue