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
00033
00039 #include "blocxx/BLOCXX_config.h"
00040 #include "blocxx/SocketAddress.hpp"
00041 #include "blocxx/ByteSwap.hpp"
00042 #include "blocxx/Assertion.hpp"
00043 #include "blocxx/Mutex.hpp"
00044 #include "blocxx/MutexLock.hpp"
00045 #include "blocxx/ExceptionIds.hpp"
00046 #include "blocxx/Format.hpp"
00047
00048 extern "C"
00049 {
00050 #if !defined(BLOCXX_WIN32)
00051 #include <netdb.h>
00052 #include <netinet/in.h>
00053 #include <arpa/inet.h>
00054 #include <sys/param.h>
00055 #include <sys/utsname.h>
00056 #include <unistd.h>
00057 #endif
00058
00059 #include <errno.h>
00060 }
00061
00062 namespace BLOCXX_NAMESPACE
00063 {
00064
00065 #ifdef BLOCXX_WIN32
00066
00067 #include <WS2tcpip.h>
00068
00069 const char *inet_ntop(int af, const void *src, char *dst, socklen_t cnt)
00070 {
00071 if (af == AF_INET)
00072 {
00073 struct sockaddr_in in;
00074 memset(&in, 0, sizeof(in));
00075 in.sin_family = AF_INET;
00076 memcpy(&in.sin_addr, src, sizeof(struct in_addr));
00077 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in), dst, cnt, NULL, 0, NI_NUMERICHOST);
00078 return dst;
00079 }
00080 else if (af == AF_INET6)
00081 {
00082 struct sockaddr_in6 in;
00083 memset(&in, 0, sizeof(in));
00084 in.sin6_family = AF_INET6;
00085 memcpy(&in.sin6_addr, src, sizeof(struct in_addr6));
00086 getnameinfo((struct sockaddr *)&in, sizeof(struct sockaddr_in6), dst, cnt, NULL, 0, NI_NUMERICHOST);
00087 return dst;
00088 }
00089 return NULL;
00090 }
00091 #endif
00092
00093 BLOCXX_DEFINE_EXCEPTION_WITH_ID(UnknownHost);
00094 BLOCXX_DEFINE_EXCEPTION_WITH_ID(SocketAddress);
00095
00096 const char* const SocketAddress::ALL_LOCAL_ADDRESSES = "0.0.0.0";
00097
00098 #if !defined(BLOCXX_WIN32)
00099
00100
00101 SocketAddress
00102 SocketAddress::getUDS(const String& filename)
00103 {
00104 SocketAddress rval;
00105 rval.m_type = UDS;
00106 rval.m_name = filename;
00107 rval.m_address = "localhost";
00108 memset(&rval.m_UDSNativeAddress, 0, sizeof(rval.m_UDSNativeAddress));
00109 rval.m_UDSNativeAddress.sun_family = AF_UNIX;
00110 strncpy(rval.m_UDSNativeAddress.sun_path, filename.c_str(),
00111 sizeof(rval.m_UDSNativeAddress.sun_path) - 1);
00112 if (::strlen(rval.m_UDSNativeAddress.sun_path) != filename.length())
00113 {
00114 BLOCXX_THROW(SocketAddressException, Format("UDS filename (%1) is too long", filename).c_str());
00115 }
00116 #ifdef BLOCXX_SOLARIS
00117 rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path) +
00118 offsetof(struct sockaddr_un, sun_path);
00119 #elif defined BLOCXX_OPENUNIX
00120 rval.m_UDSNativeAddress.sun_len = sizeof(rval.m_UDSNativeAddress);
00121 rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path) +
00122 offsetof(struct sockaddr_un, sun_path);
00123 #elif defined BLOCXX_AIX || defined BLOCXX_DARWIN
00124
00125 rval.m_UDSNativeAddress.sun_len = filename.length() + 1;
00126 rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path) +
00127 offsetof(struct sockaddr_un, sun_path) + 1;
00128 #elif defined BLOCXX_FREEBSD
00129 rval.m_nativeSize = ::strlen(rval.m_UDSNativeAddress.sun_path)
00130 + sizeof(rval.m_UDSNativeAddress.sun_len)
00131 + sizeof(rval.m_UDSNativeAddress.sun_family);
00132 #else
00133 rval.m_nativeSize = sizeof(rval.m_UDSNativeAddress.sun_family) +
00134 ::strlen(rval.m_UDSNativeAddress.sun_path);
00135 #endif
00136 return rval;
00137 }
00138
00139 #endif // #if !defined(BLOCXX_WIN32)
00140
00142 SocketAddress::SocketAddress()
00143 : m_nativeSize(0) , m_type(UNSET)
00144 {
00145 }
00146
00147 #ifndef BLOCXX_HAVE_GETHOSTBYNAME_R
00148 Mutex gethostbynameMutex;
00149 #endif
00150
00152
00153 SocketAddress
00154 SocketAddress::getByName(const String& hostName, UInt16 port)
00155 {
00156 #ifdef BLOCXX_HAVE_IPV6
00157
00158 InetSocketAddress_t sa;
00159 memset(&sa, 0, sizeof(sa));
00160 if( inet_pton(AF_INET6, hostName.c_str(), (void*)&(reinterpret_cast<sockaddr_in6*>(&sa)->sin6_addr)))
00161 {
00162 reinterpret_cast<sockaddr_in6*>(&sa)->sin6_family = AF_INET6;
00163 reinterpret_cast<sockaddr_in6*>(&sa)->sin6_port = htons(port);
00164 SocketAddress p = SocketAddress(sa);
00165 p.m_type = INET;
00166 p.m_name = hostName;
00167 return p;
00168 }
00169 #endif
00170 #if defined(BLOCXX_HAVE_GETHOSTBYNAME_R) && defined(BLOCXX_GETHOSTBYNAME_R_ARGUMENTS)
00171 hostent hostbuf;
00172 hostent* host = &hostbuf;
00173 #if (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 6)
00174 char buf[2048];
00175 int h_err = 0;
00176 if (gethostbyname_r(hostName.c_str(), &hostbuf, buf, sizeof(buf),
00177 &host, &h_err) == -1)
00178 {
00179 host = NULL;
00180 }
00181 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 5)
00182
00183 char buf[2048];
00184 int h_err(0);
00185
00186 host = gethostbyname_r(hostName.c_str(), &hostbuf, buf, sizeof(buf), &h_err);
00187
00188 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 3)
00189 hostent_data hostdata;
00190 if (gethostbyname_r(hostName.c_str(), &hostbuf, &hostdata) != 0)
00191 {
00192 host = NULL;
00193 }
00194
00195 #else
00196 #error Not yet supported: gethostbyname_r() with other argument counts.
00197 #endif
00198 #else
00199 MutexLock mlock(gethostbynameMutex);
00200 #if defined(BLOCXX_NCR)
00201 hostent* host = gethostbyname(const_cast<char *>(hostName.c_str()));
00202 #else
00203 hostent* host = gethostbyname(hostName.c_str());
00204 #endif
00205 #endif
00206
00207 if (!host)
00208 {
00209 BLOCXX_THROW(UnknownHostException, String("Unknown host: ").concat(hostName).c_str());
00210 }
00211 in_addr addr;
00212 memcpy(&addr, host->h_addr_list[0], sizeof(addr));
00213 return getFromNativeForm(addr, port, host->h_name);
00214 }
00215
00217
00218 SocketAddress
00219 SocketAddress::getFromNativeForm( const InetSocketAddress_t& nativeForm)
00220 {
00221 return SocketAddress(nativeForm);
00222 }
00223
00224 #if !defined(BLOCXX_WIN32)
00225
00226
00227 SocketAddress
00228 SocketAddress::getFromNativeForm( const UnixSocketAddress_t& nativeForm)
00229 {
00230 return SocketAddress(nativeForm);
00231 }
00232 #endif // !defined(BLOCXX_WIN32)
00233
00235
00236 SocketAddress
00237 SocketAddress::getFromNativeForm( const InetAddress_t& nativeForm,
00238 UInt16 nativePort, const String& hostName)
00239 {
00240 InetSocketAddress_t addr;
00241 memset(&addr, 0, sizeof(addr));
00242 reinterpret_cast<sockaddr_in*>(&addr)->sin_family = AF_INET;
00243 reinterpret_cast<sockaddr_in*>(&addr)->sin_port = hton16(nativePort);
00244 reinterpret_cast<sockaddr_in*>(&addr)->sin_addr = nativeForm;
00245 SocketAddress p = SocketAddress(addr);
00246 p.m_type = INET;
00247 p.m_name = hostName;
00248 return p;
00249 }
00251 const SocketAddress_t* SocketAddress::getNativeForm() const
00252 {
00253 if (m_type == INET)
00254 {
00255 return reinterpret_cast<const sockaddr*>(&m_inetNativeAddress);
00256 }
00257
00258 #if !defined(BLOCXX_WIN32)
00259 else if (m_type == UDS)
00260 {
00261 return reinterpret_cast<const sockaddr*>(&m_UDSNativeAddress);
00262 }
00263 #endif
00264
00265 return 0;
00266 }
00267
00269 const InetSocketAddress_t* SocketAddress::getInetAddress() const
00270 {
00271 return &m_inetNativeAddress;
00272 }
00273
00274 #if !defined(BLOCXX_WIN32)
00275
00276
00277
00278 const UnixSocketAddress_t* SocketAddress::getUnixAddress() const
00279 {
00280 return &m_UDSNativeAddress;
00281 }
00282 #endif
00283
00285 SocketAddress
00286 SocketAddress::getAnyLocalHost(UInt16 port)
00287 {
00288 struct in_addr addr;
00289 addr.s_addr = hton32(INADDR_ANY);
00290 SocketAddress rval = getFromNativeForm(addr, port, "localhost");
00291 char buf[256];
00292 gethostname(buf, sizeof(buf));
00293 String hname(buf);
00294 if (hname.indexOf('.') == String::npos)
00295 {
00296 #if defined(BLOCXX_HAVE_GETHOSTBYNAME_R) && defined(BLOCXX_GETHOSTBYNAME_R_ARGUMENTS)
00297 hostent hostbuf;
00298 hostent* hent = &hostbuf;
00299 #if (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 6)
00300 char local_buf[2048];
00301 int h_err = 0;
00302 if (gethostbyname_r(buf, &hostbuf, local_buf, sizeof(local_buf),
00303 &hent, &h_err) == -1)
00304 {
00305 hent = NULL;
00306 }
00307 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 5)
00308
00309 char local_buf[2048];
00310 int h_err(0);
00311
00312 hent = gethostbyname_r(buf, &hostbuf, local_buf, sizeof(local_buf), &h_err);
00313
00314 #elif (BLOCXX_GETHOSTBYNAME_R_ARGUMENTS == 3)
00315 hostent_data hostdata;
00316 if (gethostbyname_r(buf, &hostbuf, &hostdata) != 0)
00317 {
00318 hent = NULL;
00319 }
00320
00321 #else
00322 #error Not yet supported: gethostbyname_r() with other argument counts.
00323 #endif
00324 #else
00325 MutexLock mlock(gethostbynameMutex);
00326 hostent* hent = gethostbyname(buf);
00327 #endif
00328 if (hent && hent->h_name && (strlen(hent->h_name) > 0))
00329 {
00330 hname = String(hent->h_name);
00331 }
00332 }
00333 rval.m_name = hname;
00334 return rval;
00335 }
00336
00338 void SocketAddress::assignFromNativeForm(
00339 const InetSocketAddress_t* address, size_t )
00340 {
00341 m_type = INET;
00342 memcpy(&m_inetNativeAddress, address, sizeof(m_inetNativeAddress));
00343 #ifdef BLOCXX_HAVE_IPV6
00344 char buf[INET6_ADDRSTRLEN];
00345 if ( reinterpret_cast<sockaddr*>(&m_inetNativeAddress)->sa_family==AF_INET6)
00346 {
00347 m_address = inet_ntop(AF_INET6, &(reinterpret_cast<sockaddr_in6*>(&m_inetNativeAddress)->sin6_addr), buf, sizeof(buf));
00348 }
00349 else
00350 {
00351 m_address = inet_ntop(AF_INET, &(reinterpret_cast<sockaddr_in*>(&m_inetNativeAddress)->sin_addr), buf, sizeof(buf));
00352 }
00353 #else
00354 m_address = inet_ntoa( reinterpret_cast<sockaddr_in*>(&m_inetNativeAddress)->sin_addr);
00355 #endif
00356 m_nativeSize = sizeof(m_inetNativeAddress);
00357 }
00358
00359 #if !defined(BLOCXX_WIN32)
00360
00361 void SocketAddress::assignFromNativeForm(
00362 const UnixSocketAddress_t* address, size_t )
00363 {
00364 m_type = UDS;
00365 memcpy(&m_UDSNativeAddress, address, sizeof(m_UDSNativeAddress));
00366 m_address = "localhost";
00367 m_name = m_UDSNativeAddress.sun_path;
00368 m_nativeSize = sizeof(m_UDSNativeAddress);
00369 }
00370 #endif // !defined(BLOCXX_WIN32)
00371
00373 UInt16 SocketAddress::getPort() const
00374 {
00375 BLOCXX_ASSERT(m_type == INET);
00376
00377 #ifdef BLOCXX_HAVE_IPV6
00378 if ( reinterpret_cast<const sockaddr*>(&m_inetNativeAddress)->sa_family==AF_INET6)
00379 {
00380 return ntoh16(reinterpret_cast<const sockaddr_in6*>(&m_inetNativeAddress)->sin6_port);
00381 }
00382 else
00383 {
00384 return ntoh16(reinterpret_cast<const sockaddr_in*>(&m_inetNativeAddress)->sin_port);
00385 }
00386 #else
00387 return ntoh16(reinterpret_cast<const sockaddr_in*>(&m_inetNativeAddress)->sin_port);
00388 #endif
00389 }
00390
00391 #if !defined(BLOCXX_WIN32)
00392
00393 SocketAddress::SocketAddress(const UnixSocketAddress_t& nativeForm)
00394 : m_nativeSize(0), m_type(UDS)
00395 {
00396 assignFromNativeForm(&nativeForm, sizeof(nativeForm));
00397 }
00398 #endif // !defined(BLOCXX_WIN32)
00399
00401 SocketAddress::SocketAddress(const InetSocketAddress_t& nativeForm)
00402 : m_nativeSize(0), m_type(INET)
00403 {
00404 assignFromNativeForm(&nativeForm, sizeof(nativeForm));
00405 }
00406
00408 const String SocketAddress::getName() const
00409 {
00410 return m_name;
00411 }
00413 const String SocketAddress::getAddress() const
00414 {
00415 return m_address;
00416 }
00418 size_t SocketAddress::getNativeFormSize() const
00419 {
00420 return m_nativeSize;
00421 }
00423 SocketAddress SocketAddress::allocEmptyAddress(AddressType type)
00424 {
00425 if (type == INET)
00426 {
00427 InetSocketAddress_t addr;
00428 memset(&addr, 0, sizeof(addr));
00429 reinterpret_cast<sockaddr_in*>(&addr)->sin_family = AF_INET;
00430 return SocketAddress(SocketAddress::getFromNativeForm(addr));
00431 }
00432 #if !defined(BLOCXX_WIN32)
00433 else if (type == UDS)
00434 {
00435 sockaddr_un addr;
00436 memset(&addr, 0, sizeof(addr));
00437 addr.sun_family = AF_UNIX;
00438 return SocketAddress(SocketAddress::getFromNativeForm(addr));
00439 }
00440 #endif
00441
00442 BLOCXX_THROW(SocketAddressException, "Bad Address Type");
00443 }
00445 const String
00446 SocketAddress::toString() const
00447 {
00448 BLOCXX_ASSERT(m_type != UNSET);
00449 String rval;
00450 if (m_type == INET)
00451 {
00452 rval = getAddress() + ":" + String(UInt32(getPort()));
00453 }
00454 else
00455 {
00456 rval = this->m_name;
00457 }
00458 return rval;
00459 }
00460
00461 }
00462