CNetworkAddress.cpp

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

Generated on Fri Nov 6 00:18:45 2009 for synergy-plus by  doxygen 1.4.7