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
|
||||
try {
|
||||
*ARG->m_serverAddress = CNetworkAddress(argv[i], kDefaultPort);
|
||||
ARG->m_serverAddress->resolve();
|
||||
}
|
||||
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,
|
||||
ARG->m_pname, e.what(), ARG->m_pname));
|
||||
bye(kExitFailed);
|
||||
}
|
||||
}
|
||||
|
||||
// increase default filter level for daemon. the user must
|
||||
// explicitly request another level for a daemon.
|
||||
|
|
|
@ -744,6 +744,7 @@ parse(int argc, const char* const* argv)
|
|||
try {
|
||||
*ARG->m_synergyAddress = CNetworkAddress(argv[i + 1],
|
||||
kDefaultPort);
|
||||
ARG->m_synergyAddress->resolve();
|
||||
}
|
||||
catch (XSocketAddress& e) {
|
||||
LOG((CLOG_PRINT "%s: %s" BYE,
|
||||
|
|
|
@ -28,6 +28,10 @@
|
|||
<td><a href="mailto:vttom@users.sourceforge.net">Tom Chadwick</a></td>
|
||||
<td>PageUp/PageDown on X servers without mouse wheel support</td>
|
||||
</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>
|
||||
</p>
|
||||
</body>
|
||||
|
|
|
@ -74,6 +74,14 @@ CClient::connect()
|
|||
}
|
||||
|
||||
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();
|
||||
|
||||
// filter socket messages, including a packetizing filter
|
||||
|
|
|
@ -22,54 +22,56 @@
|
|||
// CNetworkAddress
|
||||
//
|
||||
|
||||
// name re-resolution adapted from a patch by Brent Priddy.
|
||||
|
||||
CNetworkAddress::CNetworkAddress() :
|
||||
m_address(NULL)
|
||||
m_address(NULL),
|
||||
m_hostname(),
|
||||
m_port(0)
|
||||
{
|
||||
// note -- make no calls to CNetwork socket interface here;
|
||||
// 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) {
|
||||
throw XSocketAddress(XSocketAddress::kBadPort, "", port);
|
||||
}
|
||||
|
||||
checkPort();
|
||||
m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
|
||||
ARCH->setAddrPort(m_address, port);
|
||||
ARCH->setAddrPort(m_address, m_port);
|
||||
}
|
||||
|
||||
CNetworkAddress::CNetworkAddress(const CNetworkAddress& addr) :
|
||||
m_address(ARCH->copyAddr(addr.m_address)),
|
||||
m_hostname(addr.m_hostname)
|
||||
m_address(addr.m_address != NULL ? ARCH->copyAddr(addr.m_address) : NULL),
|
||||
m_hostname(addr.m_hostname),
|
||||
m_port(addr.m_port)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
CNetworkAddress::CNetworkAddress(const CString& hostname_, int port) :
|
||||
m_hostname(hostname_)
|
||||
CNetworkAddress::CNetworkAddress(const CString& hostname, int port) :
|
||||
m_address(NULL),
|
||||
m_hostname(hostname),
|
||||
m_port(port)
|
||||
{
|
||||
if (port == 0) {
|
||||
throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, port);
|
||||
}
|
||||
|
||||
// check for port suffix
|
||||
CString hostname(m_hostname);
|
||||
CString::size_type i = hostname.rfind(':');
|
||||
if (i != CString::npos && i + 1 < hostname.size()) {
|
||||
CString::size_type i = m_hostname.rfind(':');
|
||||
if (i != CString::npos && i + 1 < m_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] == ':') {
|
||||
if (m_hostname[j] == ':') {
|
||||
colonNotation = true;
|
||||
dotNotation = false;
|
||||
if (hostname[j + 1] == ':') {
|
||||
if (m_hostname[j + 1] == ':') {
|
||||
doubleColon = true;
|
||||
}
|
||||
}
|
||||
else if (hostname[j] == '.' && colonNotation) {
|
||||
else if (m_hostname[j] == '.' && colonNotation) {
|
||||
dotNotation = true;
|
||||
}
|
||||
}
|
||||
|
@ -80,46 +82,25 @@ CNetworkAddress::CNetworkAddress(const CString& hostname_, int port) :
|
|||
// the user can replace the double colon with zeros to
|
||||
// disambiguate.
|
||||
if ((!doubleColon || dotNotation) || !colonNotation) {
|
||||
// parse port from hostname
|
||||
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
|
||||
const char* chostname = m_hostname.c_str();
|
||||
long suffixPort = strtol(chostname + i + 1, &end, 10);
|
||||
if (end == chostname + i + 1 || *end != '\0') {
|
||||
throw XSocketAddress(XSocketAddress::kBadPort,
|
||||
m_hostname, port);
|
||||
}
|
||||
else {
|
||||
// good port
|
||||
port = static_cast<int>(suffixPort);
|
||||
hostname.erase(i);
|
||||
m_hostname, m_port);
|
||||
}
|
||||
|
||||
// trim port from hostname
|
||||
m_hostname.erase(i);
|
||||
|
||||
// save port
|
||||
m_port = static_cast<int>(suffixPort);
|
||||
}
|
||||
}
|
||||
|
||||
// if hostname is empty then use wildcard address
|
||||
if (hostname.empty()) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
// check port number
|
||||
checkPort();
|
||||
}
|
||||
|
||||
CNetworkAddress::~CNetworkAddress()
|
||||
|
@ -139,11 +120,48 @@ CNetworkAddress::operator=(const CNetworkAddress& addr)
|
|||
if (m_address != NULL) {
|
||||
ARCH->closeAddr(m_address);
|
||||
}
|
||||
m_hostname = addr.m_hostname;
|
||||
m_address = newAddr;
|
||||
m_hostname = addr.m_hostname;
|
||||
m_port = addr.m_port;
|
||||
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
|
||||
CNetworkAddress::operator==(const CNetworkAddress& addr) const
|
||||
{
|
||||
|
@ -171,7 +189,7 @@ CNetworkAddress::getAddress() const
|
|||
int
|
||||
CNetworkAddress::getPort() const
|
||||
{
|
||||
return (m_address == NULL) ? 0 : ARCH->getAddrPort(m_address);
|
||||
return m_port;
|
||||
}
|
||||
|
||||
CString
|
||||
|
@ -179,3 +197,12 @@ CNetworkAddress::getHostname() const
|
|||
{
|
||||
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.
|
||||
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
|
||||
then this throws XSocketAddress. If \c hostname ends in ":[0-9]+" then
|
||||
that suffix is extracted and used as the port, overridding the port
|
||||
parameter. Neither the extracted port or \c port may be zero.
|
||||
it's used, otherwise it's used as a host name. If \c hostname ends
|
||||
in ":[0-9]+" then that suffix is extracted and used as the port,
|
||||
overridding the port parameter. The resulting port must be a valid
|
||||
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);
|
||||
|
||||
|
@ -52,6 +54,19 @@ public:
|
|||
|
||||
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
|
||||
//@{
|
||||
|
||||
|
@ -59,13 +74,13 @@ public:
|
|||
/*!
|
||||
Returns true if this address is equal to \p address.
|
||||
*/
|
||||
bool operator==(const CNetworkAddress&) const;
|
||||
bool operator==(const CNetworkAddress& address) const;
|
||||
|
||||
//! Check address inequality
|
||||
/*!
|
||||
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
|
||||
/*!
|
||||
|
@ -89,15 +104,19 @@ public:
|
|||
|
||||
//! 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;
|
||||
|
||||
//@}
|
||||
|
||||
private:
|
||||
void checkPort();
|
||||
|
||||
private:
|
||||
CArchNetAddress m_address;
|
||||
CString m_hostname;
|
||||
int m_port;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -780,6 +780,7 @@ CConfig::readSectionOptions(std::istream& s)
|
|||
if (name == "address") {
|
||||
try {
|
||||
m_synergyAddress = CNetworkAddress(value, kDefaultPort);
|
||||
m_synergyAddress.resolve();
|
||||
}
|
||||
catch (XSocketAddress& e) {
|
||||
throw XConfigRead(CString("invalid address argument: ") +
|
||||
|
|
Loading…
Reference in New Issue