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 
00037 #include "OW_config.h"
00038 
00039 #if defined(OW_WIN32)
00040 
00041 #include "OW_SocketBaseImpl.hpp"
00042 #include "OW_SocketUtils.hpp"
00043 #include "OW_Format.hpp"
00044 #include "OW_Assertion.hpp"
00045 #include "OW_IOException.hpp"
00046 #include "OW_Mutex.hpp"
00047 #include "OW_MutexLock.hpp"
00048 #include "OW_PosixUnnamedPipe.hpp"
00049 #include "OW_Socket.hpp"
00050 #include "OW_Thread.hpp"
00051 #include "OW_System.hpp"
00052 
00053 #include <cstdio>
00054 #include <cerrno>
00055 #include <fstream>
00056 #include <ws2tcpip.h>
00057 
00058 namespace
00059 {
00060 
00061 class SockInitializer
00062 {
00063 public:
00064    SockInitializer()
00065    {
00066       WSADATA wsaData;
00067       ::WSAStartup(MAKEWORD(2,2), &wsaData);
00068    }
00069 
00070    ~SockInitializer()
00071    {
00072       ::WSACleanup();
00073    }
00074 };
00075 
00076 
00077 SockInitializer _sockInitializer;
00078 
00080 void
00081 _closeSocket(SOCKET& sockfd)
00082 {
00083    if (sockfd != INVALID_SOCKET)
00084    {
00085       ::closesocket(sockfd);
00086       sockfd = INVALID_SOCKET;
00087    }
00088 }
00089 
00091 int
00092 getAddrFromIface(OW_NAMESPACE::InetSocketAddress_t& addr)
00093 {
00094    SOCKET sd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00095     if (sd == SOCKET_ERROR)
00096    {
00097       return -1;
00098     }
00099 
00100    int cc = -1;
00101     INTERFACE_INFO interfaceList[20];
00102     unsigned long nBytesReturned;
00103    if (::WSAIoctl(sd, SIO_GET_INTERFACE_LIST, 0, 0, &interfaceList,
00104          sizeof(interfaceList), &nBytesReturned, 0, 0) != SOCKET_ERROR)
00105    {
00106       int nNumInterfaces = nBytesReturned / sizeof(INTERFACE_INFO);
00107       for (int i = 0; i < nNumInterfaces; ++i)
00108       {
00109          u_long nFlags = interfaceList[i].iiFlags;
00110          if (nFlags & IFF_UP)
00111          {
00112             cc = 0;
00113             ::memcpy(&addr, &(interfaceList[i].iiAddress), sizeof(addr));
00114             if (!(nFlags & IFF_LOOPBACK))
00115             {
00116                break;
00117             }
00118          }
00119       }
00120    }
00121 
00122    ::closesocket(sd);
00123     return 0;
00124 }
00125 
00126 }  
00127 
00128 namespace OW_NAMESPACE
00129 {
00130 
00131 using std::istream;
00132 using std::ostream;
00133 using std::iostream;
00134 using std::ifstream;
00135 using std::ofstream;
00136 using std::fstream;
00137 using std::ios;
00138 String SocketBaseImpl::m_traceFileOut;
00139 String SocketBaseImpl::m_traceFileIn;
00140 
00142 
00143 int
00144 SocketBaseImpl::waitForEvent(HANDLE eventArg, int secsToTimeout)
00145 {
00146    DWORD timeout = (secsToTimeout != -1)
00147       ? static_cast<DWORD>(secsToTimeout * 1000)
00148       : INFINITE;
00149    
00150    int cc;
00151    if(Socket::getShutDownMechanism() != NULL)
00152    {
00153       HANDLE events[2];
00154       events[0] = Socket::getShutDownMechanism();
00155       events[1] = eventArg;
00156 
00157       DWORD index = ::WaitForMultipleObjects(
00158          2,
00159          events,
00160          FALSE,
00161          timeout);
00162 
00163       switch (index)
00164       {
00165          case WAIT_FAILED:
00166             cc = -2;
00167             break;
00168          case WAIT_TIMEOUT:
00169             cc = -1;
00170             break;
00171          default:
00172             index -= WAIT_OBJECT_0;
00173             
00174             if (index != 0)
00175             {
00176                ::ResetEvent(eventArg);
00177             }
00178             cc = static_cast<int>(index);
00179             break;
00180       }
00181    }
00182    else
00183    {
00184       switch(::WaitForSingleObject(eventArg, timeout))
00185       {
00186          case WAIT_OBJECT_0:
00187             ::ResetEvent(eventArg);
00188             cc = 1;
00189             break;
00190          case WAIT_TIMEOUT:
00191             cc = -1;
00192             break;
00193          default:
00194             cc = -2;
00195             break;
00196       }
00197    }
00198       
00199    return cc;
00200 }
00201 
00202 #pragma warning (push)
00203 #pragma warning (disable: 4355)
00204 
00206 SocketBaseImpl::SocketBaseImpl()
00207    : SelectableIFC()
00208    , IOIFC()
00209    , m_isConnected(false)
00210    , m_sockfd(INVALID_SOCKET)
00211    , m_localAddress()
00212    , m_peerAddress()
00213    , m_event(NULL)
00214    , m_recvTimeoutExprd(false)
00215    , m_streamBuf(this)
00216    , m_in(&m_streamBuf)
00217    , m_out(&m_streamBuf)
00218    , m_inout(&m_streamBuf)
00219    , m_recvTimeout(-1)
00220    , m_sendTimeout(-1)
00221    , m_connectTimeout(0)
00222 {
00223    m_out.exceptions(std::ios::badbit);
00224    m_inout.exceptions(std::ios::badbit);
00225    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00226    OW_ASSERT(m_event != NULL);
00227 }
00229 SocketBaseImpl::SocketBaseImpl(SocketHandle_t fd,
00230       SocketAddress::AddressType addrType)
00231    : SelectableIFC()
00232    , IOIFC()
00233    , m_isConnected(true)
00234    , m_sockfd(fd)
00235    , m_localAddress(SocketAddress::getAnyLocalHost())
00236    , m_peerAddress(SocketAddress::allocEmptyAddress(addrType))
00237    , m_event(NULL)
00238    , m_recvTimeoutExprd(false)
00239    , m_streamBuf(this)
00240    , m_in(&m_streamBuf)
00241    , m_out(&m_streamBuf)
00242    , m_inout(&m_streamBuf)
00243    , m_recvTimeout(-1)
00244    , m_sendTimeout(-1)
00245    , m_connectTimeout(0)
00246 {
00247    OW_ASSERT(addrType == SocketAddress::INET);
00248 
00249    m_out.exceptions(std::ios::badbit);
00250    m_inout.exceptions(std::ios::badbit);
00251    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00252    OW_ASSERT(m_event != NULL);
00253    fillInetAddrParms();
00254 }
00256 SocketBaseImpl::SocketBaseImpl(const SocketAddress& addr)
00257    : SelectableIFC()
00258    , IOIFC()
00259    , m_isConnected(false)
00260    , m_sockfd(INVALID_SOCKET)
00261    , m_localAddress(SocketAddress::getAnyLocalHost())
00262    , m_peerAddress(addr)
00263    , m_event(NULL)
00264    , m_recvTimeoutExprd(false)
00265    , m_streamBuf(this)
00266    , m_in(&m_streamBuf)
00267    , m_out(&m_streamBuf)
00268    , m_inout(&m_streamBuf)
00269    , m_recvTimeout(-1)
00270    , m_sendTimeout(-1)
00271    , m_connectTimeout(0)
00272 {
00273    m_out.exceptions(std::ios::badbit);
00274    m_inout.exceptions(std::ios::badbit);
00275    m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
00276    OW_ASSERT(m_event != NULL);
00277    connect(m_peerAddress);
00278 }
00279 
00280 #pragma warning (pop)
00281 
00283 SocketBaseImpl::~SocketBaseImpl()
00284 {
00285    try
00286    {
00287       disconnect();
00288    }
00289    catch (...)
00290    {
00291       
00292    }
00293    ::CloseHandle(m_event);
00294 }
00296 Select_t
00297 SocketBaseImpl::getSelectObj() const
00298 {
00299    Select_t st;
00300    st.event = m_event;
00301    st.sockfd = m_sockfd;
00302    st.networkevents = FD_READ | FD_WRITE;
00303    st.doreset = true;
00304    return st;
00305 }
00307 void
00308 SocketBaseImpl::connect(const SocketAddress& addr)
00309 {
00310    if (m_isConnected)
00311    {
00312       disconnect();
00313    }
00314    m_streamBuf.reset();
00315    m_in.clear();
00316    m_out.clear();
00317    m_inout.clear();
00318    OW_ASSERT(addr.getType() == SocketAddress::INET);
00319 
00320    m_sockfd = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
00321    if (m_sockfd == INVALID_SOCKET)
00322    {
00323       OW_THROW(SocketException, 
00324          Format("Failed to create a socket: %1",
00325          System::lastErrorMsg(true)).c_str());
00326    }
00327 
00328    int cc;
00329    WSANETWORKEVENTS networkEvents;
00330 
00331    
00332    if(::WSAEventSelect(m_sockfd, m_event, FD_CONNECT) != 0)
00333    {
00334       OW_THROW(SocketException, 
00335          Format("WSAEventSelect Failed: %1",
00336          System::lastErrorMsg(true)).c_str());
00337    }
00338 
00339    if (::connect(m_sockfd, addr.getNativeForm(), addr.getNativeFormSize())
00340       == SOCKET_ERROR)
00341    {
00342       int lastError = ::WSAGetLastError();
00343         if (lastError != WSAEWOULDBLOCK && lastError != WSAEINPROGRESS)
00344       {
00345          _closeSocket(m_sockfd);
00346          OW_THROW(SocketException,
00347             Format("Failed to connect to: %1: %2(%3)", addr.toString(),
00348                lastError, System::lastErrorMsg(true)).c_str());
00349       }
00350 
00351       int tmoutval = (m_connectTimeout > 0) ? m_connectTimeout : INFINITE;
00352 
00353       
00354       while (true)
00355       {
00356          
00357          if ((cc = waitForEvent(m_event, tmoutval)) < 1)
00358          {
00359             _closeSocket(m_sockfd);
00360             switch (cc)
00361             {
00362                case 0:     
00363                   OW_THROW(SocketException,
00364                      "Sockets have been shutdown");
00365                case -1: 
00366                   OW_THROW(SocketException,
00367                      Format("Win32SocketBaseImpl connection"
00368                         " timed out. Timeout val = %1",
00369                         m_connectTimeout).c_str());
00370                default: 
00371                   OW_THROW(SocketException, Format("SocketBaseImpl::"
00372                      "connect() wait failed: %1(%2)",
00373                      ::WSAGetLastError(),
00374                      System::lastErrorMsg(true)).c_str());
00375             }
00376          }
00377 
00378          
00379          if (::WSAEnumNetworkEvents(m_sockfd, m_event, &networkEvents)
00380             == SOCKET_ERROR)
00381          {
00382             _closeSocket(m_sockfd);
00383             OW_THROW(SocketException,
00384                Format("SocketBaseImpl::connect()"
00385                   " failed getting network events: %1(%2)",
00386                   ::WSAGetLastError(),
00387                   System::lastErrorMsg(true)).c_str());
00388          }
00389 
00390          
00391          if (networkEvents.lNetworkEvents & FD_CONNECT)
00392          {
00393             
00394             if (networkEvents.iErrorCode[FD_CONNECT_BIT])
00395             {
00396                ::WSASetLastError(networkEvents.iErrorCode[FD_CONNECT_BIT]);
00397                _closeSocket(m_sockfd);
00398                     OW_THROW(SocketException,
00399                   Format("SocketBaseImpl::connect() failed: %1(%2)",
00400                   ::WSAGetLastError(),
00401                   System::lastErrorMsg(true)).c_str());
00402             }
00403             break;
00404          }
00405       }  
00406    }  
00407 
00408    
00409    if(::WSAEventSelect(m_sockfd, m_event, 0) != 0)
00410    {
00411       _closeSocket(m_sockfd);
00412       OW_THROW(SocketException, 
00413          Format("Resetting socket with WSAEventSelect Failed: %1",
00414          System::lastErrorMsg(true)).c_str());
00415    }
00416    u_long ioctlarg = 0;
00417    ::ioctlsocket(m_sockfd, FIONBIO, &ioctlarg);
00418 
00419    m_isConnected = true;
00420 
00421    m_peerAddress = addr; 
00422 
00423    OW_ASSERT(addr.getType() == SocketAddress::INET);
00424 
00425    fillInetAddrParms();
00426 }
00427 
00429 void
00430 SocketBaseImpl::disconnect()
00431 {
00432    if(m_in)
00433    {
00434       m_in.clear(ios::eofbit);
00435    }
00436    if(m_out)
00437    {
00438         m_out.clear(ios::eofbit);
00439    }
00440    if(!m_inout.fail())
00441    {
00442       m_inout.clear(ios::eofbit);
00443    }
00444 
00445    ::SetEvent(m_event);
00446    _closeSocket(m_sockfd);
00447    m_isConnected = false;
00448 }
00449 
00451 void
00452 SocketBaseImpl::fillInetAddrParms()
00453 {
00454    socklen_t len;
00455    InetSocketAddress_t addr;
00456    ::memset(&addr, 0, sizeof(addr));
00457    len = sizeof(addr);
00458    bool gotAddr = false;
00459 
00460    if (m_sockfd != INVALID_SOCKET)
00461    {
00462       len = sizeof(addr);
00463       if (::getsockname(m_sockfd,
00464          reinterpret_cast<struct sockaddr*>(&addr), &len) != SOCKET_ERROR)
00465       {
00466          m_localAddress.assignFromNativeForm(&addr, len);
00467       }
00468       else if (getAddrFromIface(addr) == 0)
00469       {
00470          len = sizeof(addr);
00471          m_localAddress.assignFromNativeForm(&addr, len);
00472       }
00473 
00474       len = sizeof(addr);
00475       if (::getpeername(m_sockfd, reinterpret_cast<struct sockaddr*>(&addr),
00476          &len) != SOCKET_ERROR)
00477       {
00478          m_peerAddress.assignFromNativeForm(&addr, len);
00479       }
00480    }
00481    else if (getAddrFromIface(addr) == 0)
00482    {
00483       m_localAddress.assignFromNativeForm(&addr, len);
00484    }
00485 }
00486 
00487 static Mutex guard;
00489 int
00490 SocketBaseImpl::write(const void* dataOut, int dataOutLen, bool errorAsException)
00491 {
00492    int rc = 0;
00493    bool isError = false;
00494    if (m_isConnected)
00495    {
00496       isError = waitForOutput(m_sendTimeout);
00497       if (isError)
00498       {
00499          rc = -1;
00500       }
00501       else
00502       {
00503          rc = writeAux(dataOut, dataOutLen);
00504          if (!m_traceFileOut.empty() && rc > 0)
00505          {
00506             MutexLock ml(guard);
00507             ofstream traceFile(m_traceFileOut.c_str(), std::ios::app);
00508             if (!traceFile)
00509             {
00510                OW_THROW(IOException, "Failed opening socket dump file");
00511             }
00512             if (!traceFile.write(static_cast<const char*>(dataOut), rc))
00513             {
00514                OW_THROW(IOException, "Failed writing to socket dump");
00515             }
00516 
00517             ofstream comboTraceFile(String(m_traceFileOut + "Combo").c_str(), std::ios::app);
00518             if (!comboTraceFile)
00519             {
00520                OW_THROW(IOException, "Failed opening socket dump file");
00521             }
00522             comboTraceFile << "\n--->Out " << rc << " bytes<---\n";
00523             if (!comboTraceFile.write(static_cast<const char*>(dataOut), rc))
00524             {
00525                OW_THROW(IOException, "Failed writing to socket dump");
00526             }
00527          }
00528       }
00529    }
00530    else
00531    {
00532       rc = -1;
00533    }
00534    if (rc < 0 && errorAsException)
00535    {
00536       OW_THROW(SocketException, "SocketBaseImpl::write");
00537    }
00538    return rc;
00539 }
00541 int
00542 SocketBaseImpl::read(void* dataIn, int dataInLen, bool errorAsException)   
00543 {
00544    int rc = 0;
00545    bool isError = false;
00546    if (m_isConnected)
00547    {
00548       isError = waitForInput(m_recvTimeout);
00549       if (isError)
00550       {
00551          rc = -1;
00552       }
00553       else
00554       {
00555          rc = readAux(dataIn, dataInLen);
00556          if (!m_traceFileIn.empty() && rc > 0)
00557          {
00558             MutexLock ml(guard);
00559             ofstream traceFile(m_traceFileIn.c_str(), std::ios::app);
00560             if (!traceFile)
00561             {
00562                OW_THROW(IOException, "Failed opening tracefile");
00563             }
00564             if (!traceFile.write(reinterpret_cast<const char*>(dataIn), rc))
00565             {
00566                OW_THROW(IOException, "Failed writing to socket dump");
00567             }
00568 
00569             ofstream comboTraceFile(String(m_traceFileOut + "Combo").c_str(), std::ios::app);
00570             if (!comboTraceFile)
00571             {
00572                OW_THROW(IOException, "Failed opening socket dump file");
00573             }
00574             comboTraceFile << "\n--->In " << rc << " bytes<---\n";
00575             if (!comboTraceFile.write(reinterpret_cast<const char*>(dataIn), rc))
00576             {
00577                OW_THROW(IOException, "Failed writing to socket dump");
00578             }
00579          }
00580       }
00581    }
00582    else
00583    {
00584       rc = -1;
00585    }
00586    if (rc < 0)
00587    {
00588       if (errorAsException)
00589          OW_THROW(SocketException, "SocketBaseImpl::read");
00590    }
00591    return rc;
00592 }
00594 bool
00595 SocketBaseImpl::waitForInput(int timeOutSecs)
00596 {
00597    int rval = SocketUtils::waitForIO(m_sockfd, m_event, timeOutSecs, FD_READ);
00598    if (rval == ETIMEDOUT)
00599    {
00600       m_recvTimeoutExprd = true;
00601    }
00602    else
00603    {
00604       m_recvTimeoutExprd = false;
00605    }
00606    return (rval != 0);
00607 }
00609 bool
00610 SocketBaseImpl::waitForOutput(int timeOutSecs)
00611 {
00612    return SocketUtils::waitForIO(m_sockfd, m_event, timeOutSecs,
00613       FD_WRITE) != 0;
00614 }
00616 istream&
00617 SocketBaseImpl::getInputStream()
00618 {
00619    return m_in;
00620 }
00622 ostream&
00623 SocketBaseImpl::getOutputStream()
00624 {
00625    return m_out;
00626 }
00628 iostream&
00629 SocketBaseImpl::getIOStream()
00630 {
00631    return m_inout;
00632 }
00634 
00635 void
00636 SocketBaseImpl::setDumpFiles(const String& in, const String& out)
00637 {
00638    m_traceFileOut = out;
00639    m_traceFileIn = in;
00640 }
00641 
00642 } 
00643 
00644 #endif   // #if defined(OW_WIN32)