(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.8 and 1.34

version 1.8, 2003/05/21 11:32:22 version 1.34, 2008/09/10 17:16:07
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>  
 #else  
 # include <cctype> # include <cctype>
 #ifndef PEGASUS_OS_OS400  #include <cstring>
 #   include <unistd.h>  #include <Pegasus/Common/Sharable.h>
 #else  #include <Pegasus/Common/Logger.h>
 #   include <Pegasus/Common/OS400ConvertChar.h>  #include <Pegasus/Common/System.h>
 #   include <unistd.cleinc>  #include <Pegasus/Common/Tracer.h>
 #endif  
 #ifdef PEGASUS_OS_ZOS  
 #   include <string.h>  // added by rk for memcpy  
 #endif  
 # include <cstdlib>  
 # include <errno.h>  
 # include <fcntl.h>  
 # include <netdb.h>  
 # include <netinet/in.h>  
 # include <arpa/inet.h>  
 # include <sys/socket.h>  
 #endif  
  
 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)
   {
       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;
   
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     return ::recv(socket, (char*)ptr, size, 0);          PEGASUS_RETRY_SYSTEM_CALL(
 #elif defined(PEGASUS_OS_ZOS)              select(FD_SETSIZE, NULL, &fdwrite, &fdwrite, &timeoutValue),
     int i=::read(socket, (char*)ptr, size);              selectResult);
 #ifdef PEGASUS_HAVE_EBCDIC  #else
     __atoe_l((char *)ptr,size);          PEGASUS_RETRY_SYSTEM_CALL(
               select(FD_SETSIZE, NULL, &fdwrite, NULL, &timeoutValue),
               selectResult);
 #endif #endif
     return i;          if (selectResult == 0)
 #elif defined(PEGASUS_OS_OS400)          {
     int i=::read(socket, (char*)ptr, size);              PEG_TRACE_CSTRING(TRC_HTTP, Tracer::LEVEL1,
     AtoE((char *)ptr, size);                  "select() timed out waiting for the socket connection to be "
     return i;                      "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::LEVEL1,
                       "Did not connect, getsockopt() returned optval = %d",
                       optval));
                   return false;
               }
           }
           else
           {
               PEG_TRACE((TRC_HTTP, Tracer::LEVEL1,
                   "select() returned error code %d",
                   getSocketError()));
               return false;
           }
       }
   
       PEG_TRACE((TRC_HTTP, Tracer::LEVEL1,
           "connect() returned error code %d",
           getSocketError()));
       return false;
   }
   
   Sint32 Socket::read(SocketHandle socket, void* ptr, Uint32 size)
   {
   #ifdef PEGASUS_OS_TYPE_WINDOWS
       return ::recv(socket, (char*)ptr, size, 0);
 #else #else
     return ::read(socket, (char*)ptr, size);      int status;
       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)  #else
     char * ptr2 = (char *)malloc(size);      int status;
     int i;      PEGASUS_RETRY_SYSTEM_CALL(::write(socket, (char*)ptr, size), status);
     memcpy(ptr2,ptr,size);      return status;
 #ifdef PEGASUS_HAVE_EBCDIC  
     __etoa_l(ptr2,size);  
 #endif #endif
     i = ::write(socket, ptr2, size);  }
     free(ptr2);  
     return i;  Sint32 Socket::timedWrite(
 #elif defined(PEGASUS_OS_OS400)      SocketHandle socket,
     char * ptr2 = (char *)malloc(size);      const void* ptr,
     int i;      Uint32 size,
     memcpy(ptr2,ptr,size);      Uint32 socketWriteTimeout)
     EtoA(ptr2,size);  {
     i = ::write(socket, ptr2, size);      Sint32 bytesWritten = 0;
     free(ptr2);      Sint32 totalBytesWritten = 0;
     return i;      Boolean socketTimedOut = false;
       int selreturn = 0;
       while (1)
       {
   #ifdef PEGASUS_OS_TYPE_WINDOWS
           PEGASUS_RETRY_SYSTEM_CALL(
               ::send(socket, (const char*)ptr, size, 0), bytesWritten);
 #else #else
     return ::write(socket, (char*)ptr, size);          PEGASUS_RETRY_SYSTEM_CALL(
               ::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;
 } }
  
 void Socket::close(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
     closesocket(socket);              if (WSAGetLastError() == WSAEWOULDBLOCK)
 #else #else
     ::close(socket);              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(Sint32 socket)  void Socket::close(SocketHandle& socket)
   {
       if (socket != PEGASUS_INVALID_SOCKET)
 { {
 #ifdef PEGASUS_OS_TYPE_WINDOWS #ifdef PEGASUS_OS_TYPE_WINDOWS
     unsigned long flag = 0;          if (!closesocket(socket))
     ioctlsocket(socket, FIONBIO, &flag);          {
               socket = PEGASUS_INVALID_SOCKET;
           }
 #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 = PEGASUS_INVALID_SOCKET;
           }
 #endif #endif
 } }
   }
  
 void Socket::disableBlocking(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
     ioctlsocket(socket, FIONBIO, &flag);     ioctlsocket(socket, FIONBIO, &flag);
   #elif PEGASUS_OS_VMS
       int flag=1;                // Use "flag = 0" to enable blocking
       ioctl(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 141 
Line 254 
     {     {
         WSADATA tmp;         WSADATA tmp;
  
         if (WSAStartup(0x202, &tmp) == SOCKET_ERROR)          int err = WSAStartup(0x202, &tmp);
             WSACleanup();          if (err != 0)
           {
               throw Exception(MessageLoaderParms(
                   "Common.Socket.WSASTARTUP_FAILED.WINDOWS",
                   "WSAStartup failed with error $0.",
                   err));
           }
     }     }
  
     _socketInterfaceRefCount++;     _socketInterfaceRefCount++;
Line 159 
Line 278 
 #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);
   
           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,
                   MessageLoaderParms(
                       "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 PEGASUS_NAMESPACE_END


Legend:
Removed from v.1.8  
changed lines
  Added in v.1.34

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2