SocketAddress.cpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2004 Vintela, Inc. All rights reserved.
00003 * Copyright (C) 2005 Novell, Inc. All rights reserved.
00004 *
00005 * Redistribution and use in source and binary forms, with or without
00006 * modification, are permitted provided that the following conditions are met:
00007 *
00008 *  - Redistributions of source code must retain the above copyright notice,
00009 *    this list of conditions and the following disclaimer.
00010 *
00011 *  - Redistributions in binary form must reproduce the above copyright notice,
00012 *    this list of conditions and the following disclaimer in the documentation
00013 *    and/or other materials provided with the distribution.
00014 *
00015 *  - Neither the name of Vintela, Inc., Novell, Inc., nor the names of its
00016 *    contributors may be used to endorse or promote products derived from this
00017 *    software without specific prior written permission.
00018 *
00019 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00020 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00021 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00022 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc., Novell, Inc., OR THE 
00023 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
00024 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
00025 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 
00026 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
00027 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 
00028 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 
00029 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00030 *******************************************************************************/
00031 
00032 
00038 #include "blocxx/BLOCXX_config.h"
00039 #include "blocxx/SocketAddress.hpp"
00040 #include "blocxx/ByteSwap.hpp"
00041 #include "blocxx/Assertion.hpp"
00042 #include "blocxx/Mutex.hpp"
00043 #include "blocxx/MutexLock.hpp"
00044 #include "blocxx/ExceptionIds.hpp"
00045 
00046 extern "C"
00047 {
00048 #if !defined(BLOCXX_WIN32)
00049 #include <netdb.h>
00050 #include <netinet/in.h>
00051 #include <arpa/inet.h>
00052 #include <sys/param.h>
00053 #include <sys/utsname.h>
00054 #include <unistd.h>
00055 #endif
00056 
00057 #include <errno.h>
00058 }
00059 
00060 namespace BLOCXX_NAMESPACE
00061 {
00062 
00063 BLOCXX_DEFINE_EXCEPTION_WITH_ID(UnknownHost);
00064 BLOCXX_DEFINE_EXCEPTION_WITH_ID(SocketAddress);
00065 
00066 const char* const SocketAddress::ALL_LOCAL_ADDRESSES = "0.0.0.0";
00067 
00068 #if !defined(BLOCXX_WIN32)
00069 
00070 //static
00071 SocketAddress
00072 SocketAddress::getUDS(const String& filename)
00073 {
00074    SocketAddress rval;
00075    rval.m_type = UDS;
00076    rval.m_name = filename;
00077    rval.m_address = "localhost";
00078    memset(&rval.m_UDSNativeAddress, 0, sizeof(rval.m_UDSNativeAddress));
00079    rval.m_UDSNativeAddress.sun_family = AF_UNIX;
00080    strncpy(rval.m_UDSNativeAddress.sun_path, filename.c_str(),
00081       sizeof(rval.m_UDSNativeAddress.sun_path) - 1);
00082 #ifdef BLOCXX_SOLARIS
00083    rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path) +
00084       offsetof(struct sockaddr_un, sun_path);
00085 #elif defined BLOCXX_OPENUNIX
00086    rval.m_UDSNativeAddress.sun_len = sizeof(rval.m_UDSNativeAddress);
00087    rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path) +
00088       offsetof(struct sockaddr_un, sun_path);
00089 #elif defined BLOCXX_AIX || defined BLOCXX_DARWIN
00090    // AIX requires the NULL terminator to be included in the sizes.
00091    rval.m_UDSNativeAddress.sun_len = filename.length() + 1;
00092    rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path) +
00093       offsetof(struct sockaddr_un, sun_path) + 1;  
00094 #elif defined BLOCXX_FREEBSD
00095    rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path)
00096       + sizeof(rval.m_UDSNativeAddress.sun_len)
00097       + sizeof(rval.m_UDSNativeAddress.sun_family);
00098 #else
00099    rval.m_nativeSize = sizeof(rval.m_UDSNativeAddress.sun_family) +
00100        ::strlen(rval.m_UDSNativeAddress.sun_path);
00101 #endif
00102    return rval;
00103 }
00104 
00105 #endif   // #if !defined(BLOCXX_WIN32)
00106 
00108 SocketAddress::SocketAddress()
00109    : m_nativeSize(0) , m_type(UNSET)
00110 {
00111 }
00112 
00113 #ifndef BLOCXX_HAVE_GETHOSTBYNAME_R
00114 Mutex gethostbynameMutex;
00115 #endif
00116 
00118 //static
00119 SocketAddress
00120 SocketAddress::getByName(const String& hostName, UInt16 port)
00121 {
00122 #if defined(BLOCXX_HAVE_GETHOSTBYNAME_R) && defined(BLOCXX_GETHOSTBYNAME_R_ARGUMENTS)
00123    hostent hostbuf;
00124    hostent* host = &hostbuf;
00125 #if (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 6)
00126    char buf[2048];
00127    int h_err = 0;
00128    if (gethostbyname_r(hostName.c_str(), &hostbuf, buf, sizeof(buf),
00129                   &host, &h_err) == -1)
00130    {
00131       host = NULL;
00132    }
00133 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 5)
00134 
00135    char buf[2048];
00136    int h_err(0);
00137    // returns NULL if not successful
00138    host = gethostbyname_r(hostName.c_str(), &hostbuf, buf, sizeof(buf), &h_err);
00139 
00140 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 3)
00141    hostent_data hostdata;
00142    if (gethostbyname_r(hostName.c_str(), &hostbuf, &hostdata) != 0)
00143    {
00144       host = NULL;
00145    }
00146 
00147 #else
00148 #error Not yet supported: gethostbyname_r() with other argument counts.
00149 #endif /* BLOCXX_GETHOSTBYNAME_R_ARGUMENTS */
00150 #else
00151    MutexLock mlock(gethostbynameMutex);
00152    hostent* host = gethostbyname(hostName.c_str());
00153 #endif /* defined(BLOCXX_HAVE_GETHOSTBYNAME_R) && defined(BLOCXX_GETHOSTBYNAME_R_ARGUMENTS) */
00154 
00155    if (!host)
00156    {
00157       BLOCXX_THROW(UnknownHostException, String("Unknown host: ").concat(hostName).c_str());
00158    }
00159    in_addr addr;
00160    memcpy(&addr, host->h_addr_list[0], sizeof(addr));
00161    return getFromNativeForm(addr, port, host->h_name);
00162 }
00163 
00165 //static
00166 SocketAddress
00167 SocketAddress::getFromNativeForm( const InetSocketAddress_t& nativeForm)
00168 {
00169    return SocketAddress(nativeForm);
00170 }
00171 
00172 #if !defined(BLOCXX_WIN32)
00173 
00174 //static
00175 SocketAddress
00176 SocketAddress::getFromNativeForm( const UnixSocketAddress_t& nativeForm)
00177 {
00178    return SocketAddress(nativeForm);
00179 }
00180 #endif   // !defined(BLOCXX_WIN32)
00181 
00183 //static
00184 SocketAddress
00185 SocketAddress::getFromNativeForm( const InetAddress_t& nativeForm,
00186       UInt16 nativePort, const String& hostName)
00187 {
00188    InetSocketAddress_t addr;
00189    memset(&addr, 0, sizeof(addr));
00190    addr.sin_family = AF_INET;
00191    addr.sin_port = hton16(nativePort);
00192    addr.sin_addr = nativeForm;
00193    SocketAddress p = SocketAddress(addr);
00194    p.m_type = INET;
00195    p.m_name = hostName;
00196    return p;
00197 }
00199 const SocketAddress_t* SocketAddress::getNativeForm() const
00200 {
00201    if (m_type == INET)
00202    {
00203       return reinterpret_cast<const sockaddr*>(&m_inetNativeAddress);
00204    }
00205 
00206 #if !defined(BLOCXX_WIN32)
00207    else if (m_type == UDS)
00208    {
00209       return reinterpret_cast<const sockaddr*>(&m_UDSNativeAddress);
00210    }
00211 #endif
00212 
00213    return 0;
00214 }
00215 
00217 const InetSocketAddress_t* SocketAddress::getInetAddress() const
00218 {
00219    return &m_inetNativeAddress;
00220 }
00221 
00222 #if !defined(BLOCXX_WIN32)
00223 
00224 // Get a pointer to the UnixSocketAddress_t
00225 // precondition: getType() == UDS
00226 const UnixSocketAddress_t* SocketAddress::getUnixAddress() const
00227 {
00228    return &m_UDSNativeAddress;
00229 }
00230 #endif
00231 
00233 SocketAddress
00234 SocketAddress::getAnyLocalHost(UInt16 port)
00235 {
00236    struct in_addr addr;
00237    addr.s_addr = hton32(INADDR_ANY);
00238    SocketAddress rval = getFromNativeForm(addr, port, "localhost");
00239    char buf[256];
00240    gethostname(buf, sizeof(buf));
00241    String hname(buf);
00242    if (hname.indexOf('.') == String::npos)
00243    {
00244 #if defined(BLOCXX_HAVE_GETHOSTBYNAME_R) && defined(BLOCXX_GETHOSTBYNAME_R_ARGUMENTS)
00245       hostent hostbuf;
00246       hostent* hent = &hostbuf;
00247 #if (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 6)
00248       char local_buf[2048];
00249       int h_err = 0;
00250       if (gethostbyname_r(buf, &hostbuf, local_buf, sizeof(local_buf),
00251                      &hent, &h_err) == -1)
00252       {
00253          hent = NULL;
00254       }
00255 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 5)
00256 
00257       char local_buf[2048];
00258       int h_err(0);
00259       // returns NULL if not successful
00260       hent = gethostbyname_r(buf, &hostbuf, local_buf, sizeof(local_buf), &h_err);
00261 
00262 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 3)
00263       hostent_data hostdata;
00264       if (gethostbyname_r(buf, &hostbuf, &hostdata) != 0)
00265       {
00266          hent = NULL;
00267       }
00268 
00269 #else
00270 #error Not yet supported: gethostbyname_r() with other argument counts.
00271 #endif /* BLOCXX_GETHOSTBYNAME_R_ARGUMENTS */
00272 #else 
00273       MutexLock mlock(gethostbynameMutex);
00274       hostent* hent = gethostbyname(buf);
00275 #endif
00276       if (hent && hent->h_name && (strlen(hent->h_name) > 0))
00277       {
00278          hname = String(hent->h_name);
00279       }
00280    }
00281    rval.m_name = hname;
00282    return rval;
00283 }
00284 
00286 void SocketAddress::assignFromNativeForm(
00287    const InetSocketAddress_t* address, size_t /*size*/)
00288 {
00289    m_type = INET;
00290    memcpy(&m_inetNativeAddress, address, sizeof(m_inetNativeAddress));
00291    m_address = inet_ntoa(m_inetNativeAddress.sin_addr);
00292    m_nativeSize = sizeof(m_inetNativeAddress);
00293 }
00294 
00295 #if !defined(BLOCXX_WIN32)
00296 
00297 void SocketAddress::assignFromNativeForm(
00298    const UnixSocketAddress_t* address, size_t /*size*/)
00299 {
00300    m_type = UDS;
00301    memcpy(&m_UDSNativeAddress, address, sizeof(m_UDSNativeAddress));
00302    m_address = "localhost";
00303    m_name = m_UDSNativeAddress.sun_path;
00304    m_nativeSize = sizeof(m_UDSNativeAddress);
00305 }
00306 #endif   // !defined(BLOCXX_WIN32)
00307 
00309 UInt16 SocketAddress::getPort() const
00310 {
00311    BLOCXX_ASSERT(m_type == INET);
00312    return ntoh16(m_inetNativeAddress.sin_port);
00313 }
00314 
00315 #if !defined(BLOCXX_WIN32)
00316 
00317 SocketAddress::SocketAddress(const UnixSocketAddress_t& nativeForm)
00318    : m_nativeSize(0), m_type(UDS)
00319 {
00320    assignFromNativeForm(&nativeForm, sizeof(nativeForm));
00321 }
00322 #endif   // !defined(BLOCXX_WIN32)
00323 
00325 SocketAddress::SocketAddress(const InetSocketAddress_t& nativeForm)
00326    : m_nativeSize(0), m_type(INET)
00327 {
00328    assignFromNativeForm(&nativeForm, sizeof(nativeForm));
00329 }
00331 const String SocketAddress::getName() const
00332 {
00333    return m_name;
00334 }
00336 const String SocketAddress::getAddress() const
00337 {
00338    return m_address;
00339 }
00341 size_t SocketAddress::getNativeFormSize() const
00342 {
00343    return m_nativeSize;
00344 }
00346 SocketAddress SocketAddress::allocEmptyAddress(AddressType type)
00347 {
00348    if (type == INET)
00349    {
00350       sockaddr_in addr;
00351       memset(&addr, 0, sizeof(addr));
00352       addr.sin_family = AF_INET;
00353       return SocketAddress(SocketAddress::getFromNativeForm(addr));
00354    }
00355 #if !defined(BLOCXX_WIN32)
00356    else if (type == UDS)
00357    {
00358       sockaddr_un addr;
00359       memset(&addr, 0, sizeof(addr));
00360       addr.sun_family = AF_UNIX;
00361       return SocketAddress(SocketAddress::getFromNativeForm(addr));
00362    }
00363 #endif
00364 
00365    BLOCXX_THROW(SocketAddressException, "Bad Address Type");
00366 }
00368 const String
00369 SocketAddress::toString() const
00370 {
00371    BLOCXX_ASSERT(m_type != UNSET);
00372    String rval;
00373    if (m_type == INET)
00374    {
00375       rval = getAddress() + ":" + String(UInt32(getPort()));
00376    }
00377    else
00378    {
00379       rval = this->m_name;
00380    }
00381    return rval;
00382 }
00383 
00384 } // end namespace BLOCXX_NAMESPACE
00385 

Generated on Fri Jun 16 15:39:09 2006 for blocxx by  doxygen 1.4.6