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
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
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
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
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
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
00150 #else
00151 MutexLock mlock(gethostbynameMutex);
00152 hostent* host = gethostbyname(hostName.c_str());
00153 #endif
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
00166 SocketAddress
00167 SocketAddress::getFromNativeForm( const InetSocketAddress_t& nativeForm)
00168 {
00169 return SocketAddress(nativeForm);
00170 }
00171
00172 #if !defined(BLOCXX_WIN32)
00173
00174
00175 SocketAddress
00176 SocketAddress::getFromNativeForm( const UnixSocketAddress_t& nativeForm)
00177 {
00178 return SocketAddress(nativeForm);
00179 }
00180 #endif // !defined(BLOCXX_WIN32)
00181
00183
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
00225
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
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
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 )
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 )
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 }
00385