(file) Return to Socket.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

Diff for /pegasus/src/Pegasus/Common/Socket.cpp between version 1.11 and 1.26.4.1

version 1.11, 2003/08/14 22:01:27 version 1.26.4.1, 2008/01/02 21:05:03
Line 1 
Line 1 
 //%/////////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,  // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // The Open Group, Tivoli Systems  // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
   // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation, The Open Group.
   // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
   // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; VERITAS Software Corporation; The Open Group.
   // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
   // EMC Corporation; Symantec Corporation; The Open Group.
 // //
 // Permission is hereby granted, free of charge, to any person obtaining a copy // Permission is hereby granted, free of charge, to any person obtaining a copy
 // of this software and associated documentation files (the "Software"), to // of this software and associated documentation files (the "Software"), to
Line 21 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  
 //  
 // Modified By:  
 //  
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include "Socket.h" #include "Socket.h"
   #include "Network.h"
 #ifdef PEGASUS_OS_TYPE_WINDOWS  
 #include <windows.h>  
 # ifndef _WINSOCKAPI_  
 #   include <winsock2.h>  
 # endif  
 #else  
 # include <cctype> # include <cctype>
 #ifndef PEGASUS_OS_OS400  #include <cstring>
 #   include <unistd.h>  
 #else  
 #   include <unistd.cleinc>  
 #endif  
 #   include <string.h>  // added by rk for memcpy  
 # include <cstdlib>  
 # include <errno.h>  
 # include <fcntl.h>  
 # include <netdb.h>  
 # include <netinet/in.h>  
 # include <arpa/inet.h>  
 # include <sys/socket.h>  
 # include <errno.h>  
 #endif  
   
 #include <Pegasus/Common/Sharable.h> #include <Pegasus/Common/Sharable.h>
   #include <Pegasus/Common/Logger.h>
   #include <Pegasus/Common/System.h>
   #include <Pegasus/Common/Tracer.h>
   
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
 static Uint32 _socketInterfaceRefCount = 0; static Uint32 _socketInterfaceRefCount = 0;
  
 Sint32 Socket::read(Sint32 socket, void* ptr, Uint32 size)  Boolean Socket::timedConnect(
       SocketHandle socket,
       sockaddr* address,
       int addressLength,
       Uint32 timeoutMilliseconds)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS      int connectResult;
     return ::recv(socket, (char*)ptr, size, 0);      PEGASUS_RETRY_SYSTEM_CALL(
 #elif defined(PEGASUS_OS_ZOS)          ::connect(socket, address, addressLength), connectResult);
     int i=::read(socket, (char*)ptr, size);  
     __atoe_l((char *)ptr,size);  
     return i;  
 #else  
  
 #if defined (__GNUC__)      if (connectResult == 0)
     int ccode = TEMP_FAILURE_RETRY(::read(socket, (char*)ptr, size));      {
     return ccode;          return true;
 #else  
     return ::read(socket, (char*)ptr, size);  
 #endif  
 #endif  
 } }
  
 Sint32 Socket::write(Sint32 socket, const void* ptr, Uint32 size)      if (getSocketError() == PEGASUS_NETWORK_EINPROGRESS)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS          PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
     return ::send(socket, (const char*)ptr, size, 0);              "Connection to server in progress.  Waiting up to %u milliseconds "
 #elif defined(PEGASUS_OS_ZOS)                  "for the socket to become connected.",
     char * ptr2 = (char *)malloc(size);              timeoutMilliseconds));
     int i;  
     memcpy(ptr2,ptr,size);          fd_set fdwrite;
     __etoa_l(ptr2,size);          FD_ZERO(&fdwrite);
     i = ::write(socket, ptr2, size);          FD_SET(socket, &fdwrite);
     free(ptr2);          struct timeval timeoutValue =
     return i;              { timeoutMilliseconds/1000, timeoutMilliseconds%1000*1000 };
 #else          int selectResult = -1;
 #if (__GNUC__)  
     int ccode = TEMP_FAILURE_RETRY(::write(socket, (char*)ptr, size));          PEGASUS_RETRY_SYSTEM_CALL(
     return ccode;              select(FD_SETSIZE, NULL, &fdwrite, NULL, &timeoutValue),
 #else              selectResult);
     return ::write(socket, (char*)ptr, size);          if (selectResult == 0)
 #endif          {
 #endif              PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL2,
                   "select() timed out waiting for the socket connection to be "
                       "established.");
               return false;
           }
           else if (selectResult > 0)
           {
               int optval;
               SocketLength optlen = sizeof(int);
               getsockopt(socket, SOL_SOCKET, SO_ERROR, (char*)&optval, &optlen);
               if (optval == 0)
               {
                   PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL4,
                       "Connection with server established.");
                   return true;
               }
               else
               {
                   PEG_TRACE((TRC_HTTP, Tracer::LEVEL2,
                       "Did not connect, getsockopt() returned optval = %d",
                       optval));
                   return false;
               }
           }
           else
           {
               PEG_TRACE((TRC_HTTP, Tracer::LEVEL2,
                   "select() returned error code %d",
                   getSocketError()));
               return false;
           }
 } }
  
 void Socket::close(Sint32 socket)      PEG_TRACE((TRC_HTTP, Tracer::LEVEL2,
           "connect() returned error code %d",
           getSocketError()));
       return false;
   }
   
   Sint32 Socket::read(SocketHandle socket, void* ptr, Uint32 size)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     closesocket(socket);      return ::recv(socket, (char*)ptr, size, 0);
 #else  
 #if (__GNUC__)  
     TEMP_FAILURE_RETRY(::close(socket));  
 #else #else
     ::close(socket);      int status;
 #endif      PEGASUS_RETRY_SYSTEM_CALL(::read(socket, (char*)ptr, size), status);
       return status;
 #endif #endif
 } }
  
 int Socket::close2(Sint32 socket)  Sint32 Socket::write(SocketHandle socket, const void* ptr, Uint32 size)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     return closesocket(socket);      return ::send(socket, (const char*)ptr, size, 0);
 #else  
 #if (__GNUC__)  
     int ccode = TEMP_FAILURE_RETRY(::close(socket));  
     return ccode;  
 #else #else
     return ::close(socket);      int status;
 #endif      PEGASUS_RETRY_SYSTEM_CALL(::write(socket, (char*)ptr, size), status);
       return status;
 #endif #endif
 } }
  
   Sint32 Socket::timedWrite(
 void Socket::enableBlocking(Sint32 socket)      SocketHandle socket,
       const void* ptr,
       Uint32 size,
       Uint32 socketWriteTimeout)
   {
       Sint32 bytesWritten = 0;
       Sint32 totalBytesWritten = 0;
       Boolean socketTimedOut = false;
       int selreturn = 0;
       while (1)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 0;          PEGASUS_RETRY_SYSTEM_CALL(
     ioctlsocket(socket, FIONBIO, &flag);              ::send(socket, (const char*)ptr, size, 0), bytesWritten);
 #else #else
     int flags = fcntl(socket, F_GETFL, 0);          PEGASUS_RETRY_SYSTEM_CALL(
     flags &= ~O_NONBLOCK;              ::write(socket, (char*)ptr, size), bytesWritten);
     fcntl(socket, F_SETFL, flags);  
 #endif #endif
           // Some data written this cycle ?
           // Add it to the total amount of written data.
           if (bytesWritten > 0)
           {
               totalBytesWritten += bytesWritten;
               socketTimedOut = false;
 } }
  
 int Socket::enableBlocking2(Sint32 socket)          // All data written ? return amount of data written
           if ((Uint32)bytesWritten == size)
           {
               return totalBytesWritten;
           }
           // If data has been written partially, we resume writing data
           // this also accounts for the case of a signal interrupt
           // (i.e. errno = EINTR)
           if (bytesWritten > 0)
 { {
               size -= bytesWritten;
               ptr = (void *)((char *)ptr + bytesWritten);
               continue;
           }
           // Something went wrong
           if (bytesWritten == PEGASUS_SOCKET_ERROR)
           {
               // if we already waited for the socket to get ready, bail out
               if (socketTimedOut) return bytesWritten;
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 0;              if (WSAGetLastError() == WSAEWOULDBLOCK)
     return ioctlsocket(socket, FIONBIO, &flag);  
 #else #else
     int flags = fcntl(socket, F_GETFL, 0);              if (errno == EAGAIN || errno == EWOULDBLOCK)
     flags &= ~O_NONBLOCK;  
     return fcntl(socket, F_SETFL, flags);  
 #endif #endif
               {
                   fd_set fdwrite;
                    // max. timeout seconds waiting for the socket to get ready
                   struct timeval tv = { socketWriteTimeout, 0 };
                   FD_ZERO(&fdwrite);
                   FD_SET(socket, &fdwrite);
                   selreturn = select(FD_SETSIZE, NULL, &fdwrite, NULL, &tv);
                   if (selreturn == 0) socketTimedOut = true; // ran out of time
                   continue;
               }
               return bytesWritten;
           }
       }
 } }
  
 void Socket::disableBlocking(Sint32 socket)  void Socket::close(SocketHandle socket)
   {
       if (socket != -1)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 1;          if (!closesocket(socket))
     ioctlsocket(socket, FIONBIO, &flag);              socket = -1;
 #else #else
     int flags = fcntl(socket, F_GETFL, 0);          int status;
     flags |= O_NONBLOCK;          PEGASUS_RETRY_SYSTEM_CALL(::close(socket), status);
     fcntl(socket, F_SETFL, flags);  
           if (status == 0)
               socket = -1;
 #endif #endif
 } }
   }
  
 int Socket::disableBlocking2(Sint32 socket)  void Socket::disableBlocking(SocketHandle socket)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 1;      unsigned long flag = 1;    // Use "flag = 0" to enable blocking
     return ioctlsocket(socket, FIONBIO, &flag);      ioctlsocket(socket, FIONBIO, &flag);
 #else #else
     int flags = fcntl(socket, F_GETFL, 0);     int flags = fcntl(socket, F_GETFL, 0);
     flags |= O_NONBLOCK;      flags |= O_NONBLOCK;    // Use "flags &= ~O_NONBLOCK" to enable blocking
     return fcntl(socket, F_SETFL, flags);      fcntl(socket, F_SETFL, flags);
 #endif #endif
 } }
  
Line 199 
Line 259 
 #endif #endif
 } }
  
   //------------------------------------------------------------------------------
   //
   // _setTCPNoDelay()
   //
   //------------------------------------------------------------------------------
  
 PEGASUS_NAMESPACE_END  inline void _setTCPNoDelay(SocketHandle socket)
   {
       // This function disables "Nagle's Algorithm" also known as "the TCP delay
       // algorithm", which causes read operations to obtain whatever data is
       // already in the input queue and then wait a little longer to see if
       // more data arrives. This algorithm optimizes the case in which data is
       // sent in only one direction but severely impairs performance of round
       // trip servers. Disabling TCP delay is a standard technique for round
       // trip servers.
   
      int opt = 1;
      setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
   }
   //------------------------------------------------------------------------------
   //
   // _setInformIfNewTCPIP()
   //
   //------------------------------------------------------------------------------
   inline void _setInformIfNewTCPIP(SocketHandle socket)
   {
   #ifdef PEGASUS_OS_ZOS
      // This function enables the notification of the CIM Server that a new
      // TCPIP transport layer is active. This is needed to be aware of a
      // restart of the transport layer. When this option is in effect,
      // the accetp(), select(), and read() request will receive an errno=EIO.
      // Once this happens, the socket should be closed and create a new.
   
      int NewTcpipOn = 1;
      setibmsockopt(
          socket,
          SOL_SOCKET,
          SO_EioIfNewTP,
          (char*)&NewTcpipOn,
          sizeof(NewTcpipOn));
   #endif
   }
  
   
   SocketHandle Socket::createSocket(int domain, int type, int protocol)
   {
       SocketHandle newSocket;
   
       if (domain == AF_UNIX)
       {
           return socket(domain,type,protocol);
       }
   
       bool sendTcpipMsg = true;
   
       while (1)
       {
           newSocket = socket(domain,type,protocol);
   
           // The program should wait for transport layer to become ready.
   
           if (newSocket == PEGASUS_INVALID_SOCKET &&
              getSocketError() == PEGASUS_NETWORK_TCPIP_TRYAGAIN )
           {
              if (sendTcpipMsg)
              {
                  Logger::put_l(
                      Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
                      "Common.Socket.WAIT_FOR_TCPIP",
                      "TCP/IP temporary unavailable.");
                  sendTcpipMsg=false;
              }
   
              System::sleep(30);
              continue;
           }
           else
           {
              break;
           }
       } // wait for the transport layer become ready.
   
       // Is the socket in an unrecoverable error ?
       if (newSocket == PEGASUS_INVALID_SOCKET)
       {
           // return immediate
           return PEGASUS_INVALID_SOCKET;
       }
       else
       {
           // set aditional socket options
           _setTCPNoDelay(newSocket);
           _setInformIfNewTCPIP(newSocket);
   
           return newSocket;
       }
   }
   
   PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.11  
changed lines
  Added in v.1.26.4.1

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2