(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.25

version 1.11, 2003/08/14 22:01:27 version 1.25, 2006/10/04 11:20:36
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 23 
Line 31 
 // //
 // Author: Mike Brasher (mbrasher@bmc.com) // Author: Mike Brasher (mbrasher@bmc.com)
 // //
 // Modified By:  // Modified By: Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2513
   //              David Dillard, Symantec Corp.,  (david_dillard@symantec.com)
 // //
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include "Socket.h" #include "Socket.h"
   #include "Network.h"
   #include <cctype>
   #include <cstring>
   #include <Pegasus/Common/Sharable.h>
   #include <Pegasus/Common/Logger.h>
   #include <Pegasus/Common/System.h>
   
   //------------------------------------------------------------------------------
   //
   // PEGASUS_RETRY_SYSTEM_CALL()
   //
   //     This macro repeats the given system call until it returns something
   //     other than EINTR.
   //
   //------------------------------------------------------------------------------
  
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
 #include <windows.h>  #   define PEGASUS_RETRY_SYSTEM_CALL(EXPR, RESULT) RESULT = EXPR
 # ifndef _WINSOCKAPI_  
 #   include <winsock2.h>  
 # endif  
 #else #else
 # include <cctype>  #   define PEGASUS_RETRY_SYSTEM_CALL(EXPR, RESULT) \
 #ifndef PEGASUS_OS_OS400          while (((RESULT = (EXPR)) == -1) && (errno == EINTR))
 #   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 #endif
  
 #include <Pegasus/Common/Sharable.h>  
 PEGASUS_NAMESPACE_BEGIN PEGASUS_NAMESPACE_BEGIN
  
 static Uint32 _socketInterfaceRefCount = 0; static Uint32 _socketInterfaceRefCount = 0;
  
 Sint32 Socket::read(Sint32 socket, void* ptr, Uint32 size)  Sint32 Socket::read(SocketHandle socket, void* ptr, Uint32 size)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     return ::recv(socket, (char*)ptr, size, 0);     return ::recv(socket, (char*)ptr, size, 0);
 #elif defined(PEGASUS_OS_ZOS)  
     int i=::read(socket, (char*)ptr, size);  
     __atoe_l((char *)ptr,size);  
     return i;  
 #else  
   
 #if defined (__GNUC__)  
     int ccode = TEMP_FAILURE_RETRY(::read(socket, (char*)ptr, size));  
     return ccode;  
 #else #else
     return ::read(socket, (char*)ptr, size);      int status;
 #endif      PEGASUS_RETRY_SYSTEM_CALL(::read(socket, (char*)ptr, size), status);
       return status;
 #endif #endif
 } }
  
 Sint32 Socket::write(Sint32 socket, const void* ptr, Uint32 size)  Sint32 Socket::write(SocketHandle socket, const void* ptr, Uint32 size)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     return ::send(socket, (const char*)ptr, size, 0);     return ::send(socket, (const char*)ptr, size, 0);
 #elif defined(PEGASUS_OS_ZOS)  
     char * ptr2 = (char *)malloc(size);  
     int i;  
     memcpy(ptr2,ptr,size);  
     __etoa_l(ptr2,size);  
     i = ::write(socket, ptr2, size);  
     free(ptr2);  
     return i;  
 #else  
 #if (__GNUC__)  
     int ccode = TEMP_FAILURE_RETRY(::write(socket, (char*)ptr, size));  
     return ccode;  
 #else #else
     return ::write(socket, (char*)ptr, size);      int status;
 #endif      PEGASUS_RETRY_SYSTEM_CALL(::write(socket, (char*)ptr, size), status);
       return status;
 #endif #endif
 } }
  
 void Socket::close(Sint32 socket)  Sint32 Socket::timedWrite(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
     closesocket(socket);          PEGASUS_RETRY_SYSTEM_CALL(
 #else              ::send(socket, (const char*)ptr, size, 0), bytesWritten);
 #if (__GNUC__)  
     TEMP_FAILURE_RETRY(::close(socket));  
 #else #else
     ::close(socket);          PEGASUS_RETRY_SYSTEM_CALL(
 #endif              ::write(socket, (char*)ptr, size), bytesWritten);
 #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::close2(Sint32 socket)          // All data written ? return amount of data written
           if ((Uint32)bytesWritten == size)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS              return totalBytesWritten;
     return closesocket(socket);  
 #else  
 #if (__GNUC__)  
     int ccode = TEMP_FAILURE_RETRY(::close(socket));  
     return ccode;  
 #else  
     return ::close(socket);  
 #endif  
 #endif  
 } }
           // If data has been written partially, we resume writing data
           // this also accounts for the case of a signal interrupt
 void Socket::enableBlocking(Sint32 socket)          // (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)
     ioctlsocket(socket, FIONBIO, &flag);  
 #else #else
     int flags = fcntl(socket, F_GETFL, 0);              if (errno == EAGAIN || errno == EWOULDBLOCK)
     flags &= ~O_NONBLOCK;  
     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;
           }
       }
 } }
  
 int Socket::enableBlocking2(Sint32 socket)  void Socket::close(SocketHandle socket)
   {
       if (socket != -1)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 0;          if(!closesocket(socket))
     return 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);
     return fcntl(socket, F_SETFL, flags);  
           if (status == 0)
               socket = -1;
 #endif #endif
 } }
   }
  
 void Socket::disableBlocking(Sint32 socket)  void Socket::enableBlocking(SocketHandle socket)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 1;      unsigned long flag = 0;
     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;
     fcntl(socket, F_SETFL, flags);     fcntl(socket, F_SETFL, flags);
 #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;
     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;
     return fcntl(socket, F_SETFL, flags);      fcntl(socket, F_SETFL, flags);
 #endif #endif
 } }
  
Line 199 
Line 217 
 #endif #endif
 } }
  
   //------------------------------------------------------------------------------
   //
   // _setTCPNoDelay()
   //
   //------------------------------------------------------------------------------
   
   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 PEGASUS_NAMESPACE_END
  


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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2