OW_SocketAddress.cpp

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

Generated on Thu Feb 9 08:48:11 2006 for openwbem by  doxygen 1.4.6