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