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_SocketException.hpp"
00038 #include "OW_SocketUtils.hpp"
00039 #include "OW_PosixUnnamedPipe.hpp"
00040 #include "OW_Assertion.hpp"
00041 #include "OW_Socket.hpp"
00042 #include "OW_Format.hpp"
00043 #include "OW_Thread.hpp"
00044 #include "OW_System.hpp"
00045 #include "OW_Select.hpp"
00046
00047 #ifndef OW_HAVE_GETHOSTBYNAME_R
00048 #include "OW_Mutex.hpp"
00049 #include "OW_MutexLock.hpp"
00050 #endif
00051
00052 extern "C"
00053 {
00054 #if !defined(OW_WIN32)
00055 #include <ctype.h>
00056 #include <sys/types.h>
00057 #include <sys/wait.h>
00058 #include <sys/time.h>
00059 #include <sys/socket.h>
00060 #ifdef OW_HAVE_SYS_RESOURCE_H
00061 #include <sys/resource.h>
00062 #endif
00063 #include <netdb.h>
00064 #include <arpa/inet.h>
00065 #include <unistd.h>
00066 #endif
00067 }
00068
00069 #include <cstring>
00070 #include <cstdio>
00071 #include <cerrno>
00072
00073 namespace OW_NAMESPACE
00074 {
00075
00076 namespace SocketUtils
00077 {
00078
00080 String
00081 inetAddrToString(UInt64 addr)
00082 {
00083 struct in_addr iaddr;
00084 iaddr.s_addr = addr;
00085 String s(inet_ntoa(iaddr));
00086 return s;
00087 }
00088 #ifndef MAX
00089 #define MAX(A,B) (((A) > (B))? (A): (B))
00090 #endif
00091
00092 #if defined(OW_WIN32)
00093 int
00094 waitForIO(SocketHandle_t fd, HANDLE eventArg, int timeOutSecs,
00095 long networkEvents)
00096 {
00097 DWORD timeout = (timeOutSecs != -1)
00098 ? static_cast<DWORD>(timeOutSecs * 1000)
00099 : INFINITE;
00100
00101 if (networkEvents != -1L)
00102 {
00103 if(::WSAEventSelect(fd, eventArg, networkEvents) != 0)
00104 {
00105 OW_THROW(SocketException,
00106 Format("WSAEventSelect failed in waitForIO: %1",
00107 System::lastErrorMsg(true)).c_str());
00108 }
00109 }
00110
00111 int cc;
00112 if(Socket::getShutDownMechanism() != NULL)
00113 {
00114 HANDLE events[2];
00115 events[0] = Socket::getShutDownMechanism();
00116 events[1] = eventArg;
00117
00118 DWORD index = ::WaitForMultipleObjects(
00119 2,
00120 events,
00121 FALSE,
00122 timeout);
00123
00124 switch (index)
00125 {
00126 case WAIT_FAILED:
00127 cc = -1;
00128 break;
00129 case WAIT_TIMEOUT:
00130 cc = ETIMEDOUT;
00131 break;
00132 default:
00133 index -= WAIT_OBJECT_0;
00134
00135 if (index != 0)
00136 {
00137 ::ResetEvent(eventArg);
00138 cc = 0;
00139 }
00140 else
00141 {
00142
00143 cc = -2;
00144 }
00145 break;
00146 }
00147 }
00148 else
00149 {
00150 switch(::WaitForSingleObject(eventArg, timeout))
00151 {
00152 case WAIT_OBJECT_0:
00153 ::ResetEvent(eventArg);
00154 cc = 0;
00155 break;
00156 case WAIT_TIMEOUT:
00157 cc = ETIMEDOUT;
00158 break;
00159 default:
00160 cc = -1;
00161 break;
00162 }
00163 }
00164
00165
00166 if(::WSAEventSelect(fd, eventArg, 0) != 0)
00167 {
00168 OW_THROW(SocketException,
00169 Format("Resetting socket with WSAEventSelect failed: %1",
00170 System::lastErrorMsg(true)).c_str());
00171 }
00172 u_long ioctlarg = 0;
00173 ::ioctlsocket(fd, FIONBIO, &ioctlarg);
00174 return cc;
00175 }
00176
00177 #else
00178
00179 int
00180 waitForIO(SocketHandle_t fd, int timeOutSecs, SocketFlags::EWaitDirectionFlag waitFlag)
00181 {
00182 if (fd == -1)
00183 {
00184 errno = EBADF;
00185 return -1;
00186 }
00187
00188 Select::SelectObject so(fd);
00189 if (waitFlag == SocketFlags::E_WAIT_FOR_INPUT)
00190 {
00191 so.waitForRead = true;
00192 }
00193 else if (waitFlag == SocketFlags::E_WAIT_FOR_OUTPUT)
00194 {
00195 so.waitForWrite = true;
00196 }
00197 else
00198 {
00199 so.waitForRead = true;
00200 so.waitForWrite = true;
00201 }
00202 Select::SelectObjectArray selarray;
00203 selarray.push_back(so);
00204
00205 PosixUnnamedPipeRef lUPipe;
00206 int pipefd = -1;
00207 if (Socket::getShutDownMechanism())
00208 {
00209 UnnamedPipeRef foo = Socket::getShutDownMechanism();
00210 lUPipe = foo.cast_to<PosixUnnamedPipe>();
00211 OW_ASSERT(lUPipe);
00212 pipefd = lUPipe->getInputHandle();
00213 }
00214 if (pipefd != -1)
00215 {
00216 so = Select::SelectObject(pipefd);
00217 so.waitForRead = true;
00218 selarray.push_back(so);
00219 }
00220
00221 int rc = Select::selectRW(selarray, timeOutSecs*1000);
00222 switch (rc)
00223 {
00224 case Select::SELECT_TIMEOUT:
00225 rc = ETIMEDOUT;
00226 break;
00227 case 2:
00228 rc = -1;
00229 break;
00230 case 1:
00231 if (pipefd != -1)
00232 {
00233 if (selarray[1].readAvailable)
00234 {
00235 rc = -1;
00236 }
00237 }
00238 if (selarray[0].writeAvailable || selarray[0].readAvailable)
00239 {
00240 rc = 0;
00241 }
00242 break;
00243 default:
00244 rc = -1;
00245 }
00246 return rc;
00247
00248 }
00249 #endif //
00250
00251 #ifndef OW_HAVE_GETHOSTBYNAME_R
00252 }
00253 extern Mutex gethostbynameMutex;
00254 namespace SocketUtils {
00255 #endif
00256
00257 #ifndef OW_WIN32
00258 String getFullyQualifiedHostName()
00259 {
00260 char hostName [2048];
00261 if (gethostname (hostName, sizeof(hostName)) == 0)
00262 {
00263 #ifndef OW_HAVE_GETHOSTBYNAME_R
00264 MutexLock lock(gethostbynameMutex);
00265 struct hostent *he;
00266 if ((he = gethostbyname (hostName)) != 0)
00267 {
00268 return he->h_name;
00269 }
00270 else
00271 {
00272 OW_THROW(SocketException, Format("SocketUtils::getFullyQualifiedHostName: gethostbyname failed: %1", h_errno).c_str());
00273 }
00274 #else
00275 hostent hostbuf;
00276 hostent* host = &hostbuf;
00277 #if (OW_GETHOSTBYNAME_R_ARGUMENTS == 6 || OW_GETHOSTBYNAME_R_ARGUMENTS == 5)
00278 char buf[2048];
00279 int h_err = 0;
00280 #elif (OW_GETHOSTBYNAME_R_ARGUMENTS == 3)
00281 hostent_data hostdata;
00282 int h_err = 0;
00283 #else
00284 #error Not yet supported: gethostbyname_r() with other argument counts.
00285 #endif
00286
00287
00288
00289 bool worked = false;
00290 for (int i = 0; i < 10 && (!worked || host == 0); ++i)
00291 {
00292 #if (OW_GETHOSTBYNAME_R_ARGUMENTS == 6)
00293 if (gethostbyname_r(hostName, &hostbuf, buf, sizeof(buf),
00294 &host, &h_err) != -1)
00295 {
00296 worked = true;
00297 break;
00298 }
00299 #elif (OW_GETHOSTBYNAME_R_ARGUMENTS == 5)
00300
00301 if ((host = gethostbyname_r(hostName, &hostbuf, buf, sizeof(buf), &h_err))) {
00302 worked = true;
00303 break;
00304 }
00305 #elif (OW_GETHOSTBYNAME_R_ARGUMENTS == 3)
00306 if (gethostbyname_r(hostName, &hostbuf, &hostdata) == 0)
00307 {
00308 worked = true;
00309 break;
00310 }
00311 else
00312 {
00313 h_err = h_errno;
00314 }
00315 #else
00316 #error Not yet supported: gethostbyname_r() with other argument counts.
00317 #endif
00318 }
00319 if (worked && host != 0)
00320 {
00321 return host->h_name;
00322 }
00323 else
00324 {
00325 OW_THROW(SocketException, Format("SocketUtils::getFullyQualifiedHostName: gethostbyname_r(%1) failed: %2", hostName, h_err).c_str());
00326 }
00327 #endif
00328 }
00329 else
00330 {
00331 OW_THROW(SocketException, Format("SocketUtils::getFullyQualifiedHostName: gethostname failed: %1(%2)", errno, strerror(errno)).c_str());
00332 }
00333 return "";
00334 }
00335 #else
00336
00337 String getFullyQualifiedHostName()
00338 {
00339 String rv;
00340 struct hostent *hostentp;
00341 char bfr[1024], ipaddrstr[128];
00342 struct in_addr iaHost;
00343
00344 if(gethostname(bfr, sizeof(bfr)-1) == SOCKET_ERROR)
00345 {
00346 OW_THROW(SocketException,
00347 Format("SocketUtils::getFullyQualifiedHostName: gethostname failed: %1(%2)",
00348 WSAGetLastError(), System::lastErrorMsg(true)).c_str());
00349 }
00350
00351 if(strchr(bfr, '.'))
00352 {
00353
00354 return String(bfr);
00355 }
00356
00357 if((hostentp = gethostbyname(bfr)) == NULL)
00358 {
00359 OW_THROW(SocketException,
00360 Format("SocketUtils::getFullyQualifiedHostName: gethostbyname"
00361 " failed: %1(%2)", WSAGetLastError(),
00362 System::lastErrorMsg(true)).c_str());
00363 }
00364
00365 if(strchr(hostentp->h_name, '.'))
00366 {
00367 rv = hostentp->h_name;
00368 }
00369 else
00370 {
00371 rv = inet_ntoa(*(struct in_addr*) (hostentp->h_addr_list[0]));
00372 iaHost.s_addr = inet_addr(rv.c_str());
00373 if(iaHost.s_addr != INADDR_NONE)
00374 {
00375 hostentp = gethostbyaddr((const char*)&iaHost,
00376 sizeof(struct in_addr), AF_INET);
00377 if(hostentp)
00378 {
00379 if(strchr(hostentp->h_name, '.'))
00380 {
00381
00382 rv = hostentp->h_name;
00383 }
00384 }
00385 }
00386 }
00387
00388 return rv;
00389 }
00390 #endif
00391
00392
00393 }
00394
00395 }
00396