• Main Page
  • Classes
  • Files
  • File List

CNetworkAddress.cpp

00001 /*
00002  * synergy -- mouse and keyboard sharing utility
00003  * Copyright (C) 2012 Bolton Software Ltd.
00004  * Copyright (C) 2002 Chris Schoeneman
00005  * 
00006  * This package is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * found in the file COPYING that should have accompanied this file.
00009  * 
00010  * This package is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  * GNU General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include "CNetworkAddress.h"
00020 #include "XSocket.h"
00021 #include "CArch.h"
00022 #include "XArch.h"
00023 #include <cstdlib>
00024 
00025 //
00026 // CNetworkAddress
00027 //
00028 
00029 // name re-resolution adapted from a patch by Brent Priddy.
00030 
00031 CNetworkAddress::CNetworkAddress() :
00032     m_address(NULL),
00033     m_hostname(),
00034     m_port(0)
00035 {
00036     // note -- make no calls to CNetwork socket interface here;
00037     // we're often called prior to CNetwork::init().
00038 }
00039 
00040 CNetworkAddress::CNetworkAddress(int port) :
00041     m_address(NULL),
00042     m_hostname(),
00043     m_port(port)
00044 {
00045     checkPort();
00046     m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
00047     ARCH->setAddrPort(m_address, m_port);
00048 }
00049 
00050 CNetworkAddress::CNetworkAddress(const CNetworkAddress& addr) :
00051     m_address(addr.m_address != NULL ? ARCH->copyAddr(addr.m_address) : NULL),
00052     m_hostname(addr.m_hostname),
00053     m_port(addr.m_port)
00054 {
00055     // do nothing
00056 }
00057 
00058 CNetworkAddress::CNetworkAddress(const CString& hostname, int port) :
00059     m_address(NULL),
00060     m_hostname(hostname),
00061     m_port(port)
00062 {
00063     // check for port suffix
00064     CString::size_type i = m_hostname.rfind(':');
00065     if (i != CString::npos && i + 1 < m_hostname.size()) {
00066         // found a colon.  see if it looks like an IPv6 address.
00067         bool colonNotation = false;
00068         bool dotNotation   = false;
00069         bool doubleColon   = false;
00070         for (CString::size_type j = 0; j < i; ++j) {
00071             if (m_hostname[j] == ':') {
00072                 colonNotation = true;
00073                 dotNotation   = false;
00074                 if (m_hostname[j + 1] == ':') {
00075                     doubleColon = true;
00076                 }
00077             }
00078             else if (m_hostname[j] == '.' && colonNotation) {
00079                 dotNotation = true;
00080             }
00081         }
00082 
00083         // port suffix is ambiguous with IPv6 notation if there's
00084         // a double colon and the end of the address is not in dot
00085         // notation.  in that case we assume it's not a port suffix.
00086         // the user can replace the double colon with zeros to
00087         // disambiguate.
00088         if ((!doubleColon || dotNotation) || !colonNotation) {
00089             // parse port from hostname
00090             char* end;
00091             const char* chostname = m_hostname.c_str();
00092             long suffixPort = strtol(chostname + i + 1, &end, 10);
00093             if (end == chostname + i + 1 || *end != '\0') {
00094                 throw XSocketAddress(XSocketAddress::kBadPort,
00095                                             m_hostname, m_port);
00096             }
00097 
00098             // trim port from hostname
00099             m_hostname.erase(i);
00100 
00101             // save port
00102             m_port = static_cast<int>(suffixPort);
00103         }
00104     }
00105 
00106     // check port number
00107     checkPort();
00108 }
00109 
00110 CNetworkAddress::~CNetworkAddress()
00111 {
00112     if (m_address != NULL) {
00113         ARCH->closeAddr(m_address);
00114     }
00115 }
00116 
00117 CNetworkAddress&
00118 CNetworkAddress::operator=(const CNetworkAddress& addr)
00119 {
00120     CArchNetAddress newAddr = NULL;
00121     if (addr.m_address != NULL) {
00122         newAddr = ARCH->copyAddr(addr.m_address);
00123     }
00124     if (m_address != NULL) {
00125         ARCH->closeAddr(m_address);
00126     }
00127     m_address  = newAddr;
00128     m_hostname = addr.m_hostname;
00129     m_port     = addr.m_port;
00130     return *this;
00131 }
00132 
00133 void
00134 CNetworkAddress::resolve()
00135 {
00136     // discard previous address
00137     if (m_address != NULL) {
00138         ARCH->closeAddr(m_address);
00139         m_address = NULL;
00140     }
00141 
00142     try {
00143         // if hostname is empty then use wildcard address otherwise look
00144         // up the name.
00145         if (m_hostname.empty()) {
00146             m_address = ARCH->newAnyAddr(IArchNetwork::kINET);
00147         }
00148         else {
00149             m_address = ARCH->nameToAddr(m_hostname);
00150         }
00151     }
00152     catch (XArchNetworkNameUnknown&) {
00153         throw XSocketAddress(XSocketAddress::kNotFound, m_hostname, m_port);
00154     }
00155     catch (XArchNetworkNameNoAddress&) {
00156         throw XSocketAddress(XSocketAddress::kNoAddress, m_hostname, m_port);
00157     }
00158     catch (XArchNetworkNameUnsupported&) {
00159         throw XSocketAddress(XSocketAddress::kUnsupported, m_hostname, m_port);
00160     }
00161     catch (XArchNetworkName&) {
00162         throw XSocketAddress(XSocketAddress::kUnknown, m_hostname, m_port);
00163     }
00164 
00165     // set port in address
00166     ARCH->setAddrPort(m_address, m_port);
00167 }
00168 
00169 bool
00170 CNetworkAddress::operator==(const CNetworkAddress& addr) const
00171 {
00172     return ARCH->isEqualAddr(m_address, addr.m_address);
00173 }
00174 
00175 bool
00176 CNetworkAddress::operator!=(const CNetworkAddress& addr) const
00177 {
00178     return !operator==(addr);
00179 }
00180 
00181 bool
00182 CNetworkAddress::isValid() const
00183 {
00184     return (m_address != NULL);
00185 }
00186 
00187 const CArchNetAddress&
00188 CNetworkAddress::getAddress() const
00189 {
00190     return m_address;
00191 }
00192 
00193 int
00194 CNetworkAddress::getPort() const
00195 {
00196     return m_port;
00197 }
00198 
00199 CString
00200 CNetworkAddress::getHostname() const
00201 {
00202     return m_hostname;
00203 }
00204 
00205 void
00206 CNetworkAddress::checkPort()
00207 {
00208     // check port number
00209     if (m_port <= 0 || m_port > 65535) {
00210         throw XSocketAddress(XSocketAddress::kBadPort, m_hostname, m_port);
00211     }
00212 }

Generated on Thu Jun 20 2013 00:00:05 for Synergy by  doxygen 1.7.1