00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
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 
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    
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 
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    
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 
00148 #else
00149    MutexLock mlock(gethostbynameMutex);
00150    hostent* host = gethostbyname(hostName.c_str());
00151 #endif 
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 
00164 SocketAddress
00165 SocketAddress::getFromNativeForm( const InetSocketAddress_t& nativeForm)
00166 {
00167    return SocketAddress(nativeForm);
00168 }
00169 
00170 #if !defined(OW_WIN32)
00171 
00172 
00173 SocketAddress
00174 SocketAddress::getFromNativeForm( const UnixSocketAddress_t& nativeForm)
00175 {
00176    return SocketAddress(nativeForm);
00177 }
00178 #endif   // !defined(OW_WIN32)
00179 
00181 
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 
00223 
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       
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 
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 )
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 )
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 } 
00383