(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.21 and 1.27.4.1

version 1.21, 2005/10/05 20:28:32 version 1.27.4.1, 2008/01/02 21:00:39
Line 1 
Line 1 
 //%2005////////////////////////////////////////////////////////////////////////  //%2006////////////////////////////////////////////////////////////////////////
 // //
 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems. // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
Line 8 
Line 8 
 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group. // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.; // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 // EMC Corporation; VERITAS Software Corporation; The Open Group. // 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 27 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (mbrasher@bmc.com)  
 //  
 // 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"
 #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(PEGASUS_SOCKET socket, void* ptr, Uint32 size)  Boolean Socket::timedConnect(
       SocketHandle socket,
       sockaddr* address,
       int addressLength,
       Uint32 timeoutMilliseconds)
   {
       int connectResult;
       PEGASUS_RETRY_SYSTEM_CALL(
           ::connect(socket, address, addressLength), connectResult);
   
       if (connectResult == 0)
       {
           return true;
       }
   
       if (getSocketError() == PEGASUS_NETWORK_EINPROGRESS)
       {
           PEG_TRACE((TRC_HTTP, Tracer::LEVEL4,
               "Connection to server in progress.  Waiting up to %u milliseconds "
                   "for the socket to become connected.",
               timeoutMilliseconds));
   
           fd_set fdwrite;
           FD_ZERO(&fdwrite);
           FD_SET(socket, &fdwrite);
           struct timeval timeoutValue =
               { timeoutMilliseconds/1000, timeoutMilliseconds%1000*1000 };
           int selectResult = -1;
   
           PEGASUS_RETRY_SYSTEM_CALL(
               select(FD_SETSIZE, NULL, &fdwrite, NULL, &timeoutValue),
               selectResult);
           if (selectResult == 0)
           {
               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;
           }
       }
   
       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
     return ::recv(socket, (char*)ptr, size, 0);     return ::recv(socket, (char*)ptr, size, 0);
 #else #else
 #if defined (__GNUC__) && !defined(PEGASUS_OS_SOLARIS) && !defined(PEGASUS_OS_DARWIN) && !defined(PEGASUS_OS_LSB)      int status;
     int ccode = TEMP_FAILURE_RETRY(::read(socket, (char*)ptr, size));      PEGASUS_RETRY_SYSTEM_CALL(::read(socket, (char*)ptr, size), status);
     return ccode;      return status;
 #else  
     return ::read(socket, (char*)ptr, size);  
 #endif  
 #endif #endif
 } }
  
 Sint32 Socket::write(PEGASUS_SOCKET 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);
 #else #else
 #if (__GNUC__) && !defined(PEGASUS_OS_SOLARIS) && !defined(PEGASUS_OS_DARWIN) && !defined(PEGASUS_OS_LSB)      int status;
     int ccode = TEMP_FAILURE_RETRY(::write(socket, (char*)ptr, size));      PEGASUS_RETRY_SYSTEM_CALL(::write(socket, (char*)ptr, size), status);
     return ccode;      return status;
 #else  
     return ::write(socket, (char*)ptr, size);  
 #endif  
 #endif #endif
 } }
  
 void Socket::close(PEGASUS_SOCKET socket)  Sint32 Socket::timedWrite(
       SocketHandle socket,
       const void* ptr,
       Uint32 size,
       Uint32 socketWriteTimeout)
 { {
   if(-1 != socket)      Sint32 bytesWritten = 0;
       Sint32 totalBytesWritten = 0;
       Boolean socketTimedOut = false;
       int selreturn = 0;
       while (1)
    {    {
     #ifdef PEGASUS_OS_TYPE_WINDOWS     #ifdef PEGASUS_OS_TYPE_WINDOWS
     if(!closesocket(socket)) socket=-1;          PEGASUS_RETRY_SYSTEM_CALL(
               ::send(socket, (const char*)ptr, size, 0), bytesWritten);
     #else     #else
     #if (__GNUC__) && !defined(PEGASUS_OS_SOLARIS) && !defined(PEGASUS_OS_DARWIN) && !defined(PEGASUS_OS_LSB)          PEGASUS_RETRY_SYSTEM_CALL(
        if(!TEMP_FAILURE_RETRY(::close(socket))) socket = -1;              ::write(socket, (char*)ptr, size), bytesWritten);
     #else  
        if(!::close(socket)) socket = -1;  
     #endif     #endif
           // Some data written this cycle ?
           // Add it to the total amount of written data.
           if (bytesWritten > 0)
           {
               totalBytesWritten += bytesWritten;
               socketTimedOut = false;
           }
   
           // 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
               if (WSAGetLastError() == WSAEWOULDBLOCK)
   #else
               if (errno == EAGAIN || errno == EWOULDBLOCK)
     #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::enableBlocking(PEGASUS_SOCKET 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))
     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
 } }
   }
  
 void Socket::disableBlocking(PEGASUS_SOCKET 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
     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
     fcntl(socket, F_SETFL, flags);     fcntl(socket, F_SETFL, flags);
 #endif #endif
 } }
Line 157 
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);
   
           if ((newSocket != PEGASUS_INVALID_SOCKET) ||
               (getSocketError() != PEGASUS_NETWORK_TRYAGAIN))
           {
               break;
           }
   
   #ifdef PEGASUS_OS_ZOS
           // The program should wait for transport layer to become ready.
   
           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);
   #endif
       } // 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.21  
changed lines
  Added in v.1.27.4.1

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2