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

  1 karl  1.22 //%2006////////////////////////////////////////////////////////////////////////
  2 mike  1.2  //
  3 karl  1.17 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
  4            // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
  5            // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
  6 karl  1.14 // IBM Corp.; EMC Corporation, The Open Group.
  7 karl  1.17 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
  8            // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
  9 karl  1.18 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 10            // EMC Corporation; VERITAS Software Corporation; The Open Group.
 11 karl  1.22 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
 12            // EMC Corporation; Symantec Corporation; The Open Group.
 13 mike  1.2  //
 14            // Permission is hereby granted, free of charge, to any person obtaining a copy
 15 kumpf 1.4  // of this software and associated documentation files (the "Software"), to
 16            // deal in the Software without restriction, including without limitation the
 17            // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 18 mike  1.2  // sell copies of the Software, and to permit persons to whom the Software is
 19            // furnished to do so, subject to the following conditions:
 20 karl  1.22 // 
 21 kumpf 1.4  // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 22 mike  1.2  // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 23            // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 24 kumpf 1.4  // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 25            // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 26            // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 27 mike  1.2  // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 28            // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 29            //
 30            //==============================================================================
 31            //
 32            // Author: Mike Brasher (mbrasher@bmc.com)
 33            //
 34 joyce.j 1.19 // Modified By: Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#2513
 35 david.dillard 1.20 //              David Dillard, Symantec Corp.,  (david_dillard@symantec.com)
 36 mike          1.2  //
 37                    //%/////////////////////////////////////////////////////////////////////////////
 38                    
 39                    #include "Socket.h"
 40 mike          1.23 #include "Network.h"
 41                    #include <cctype>
 42                    #include <cstring>
 43                    #include <Pegasus/Common/Sharable.h>
 44 thilo.boehm   1.25 #include <Pegasus/Common/Logger.h>
 45                    #include <Pegasus/Common/System.h>
 46 mike          1.23 
 47                    //------------------------------------------------------------------------------
 48                    //
 49                    // PEGASUS_RETRY_SYSTEM_CALL()
 50                    //
 51                    //     This macro repeats the given system call until it returns something
 52                    //     other than EINTR.
 53                    //
 54                    //------------------------------------------------------------------------------
 55 mike          1.2  
 56                    #ifdef PEGASUS_OS_TYPE_WINDOWS
 57 mike          1.23 #   define PEGASUS_RETRY_SYSTEM_CALL(EXPR, RESULT) RESULT = EXPR
 58                    #else
 59                    #   define PEGASUS_RETRY_SYSTEM_CALL(EXPR, RESULT) \
 60                            while (((RESULT = (EXPR)) == -1) && (errno == EINTR))
 61 mike          1.2  #endif
 62                    
 63                    PEGASUS_NAMESPACE_BEGIN
 64                    
 65                    static Uint32 _socketInterfaceRefCount = 0;
 66                    
 67 mike          1.23 Sint32 Socket::read(SocketHandle socket, void* ptr, Uint32 size)
 68 mike          1.2  {
 69                    #ifdef PEGASUS_OS_TYPE_WINDOWS
 70                        return ::recv(socket, (char*)ptr, size, 0);
 71                    #else
 72 mike          1.23     int status;
 73                        PEGASUS_RETRY_SYSTEM_CALL(::read(socket, (char*)ptr, size), status);
 74                        return status;
 75 mday          1.11 #endif
 76 mike          1.2  }
 77                    
 78 mike          1.23 Sint32 Socket::write(SocketHandle socket, const void* ptr, Uint32 size)
 79 mike          1.2  {
 80                    #ifdef PEGASUS_OS_TYPE_WINDOWS
 81                        return ::send(socket, (const char*)ptr, size, 0);
 82                    #else
 83 mike          1.23     int status;
 84                        PEGASUS_RETRY_SYSTEM_CALL(::write(socket, (char*)ptr, size), status);
 85                        return status;
 86 mday          1.11 #endif
 87 mike          1.2  }
 88                    
 89 marek         1.24 Sint32 Socket::timedWrite(SocketHandle socket, 
 90                                              const void* ptr, 
 91                                              Uint32 size, 
 92                                              Uint32 socketWriteTimeout)
 93                    {
 94                        Sint32 bytesWritten = 0;
 95                        Sint32 totalBytesWritten = 0;
 96                        Boolean socketTimedOut = false;
 97                        int selreturn = 0;
 98                        while (1)
 99                        {
100                    #ifdef PEGASUS_OS_TYPE_WINDOWS
101                            PEGASUS_RETRY_SYSTEM_CALL(
102                                ::send(socket, (const char*)ptr, size, 0), bytesWritten);
103                    #else
104                            PEGASUS_RETRY_SYSTEM_CALL(
105                                ::write(socket, (char*)ptr, size), bytesWritten);
106                    #endif
107                            // Some data written this cycle ? 
108                            // Add it to the total amount of written data.
109                            if (bytesWritten > 0)
110 marek         1.24         {
111                                totalBytesWritten += bytesWritten;
112                                socketTimedOut = false;
113                            }
114                    
115                            // All data written ? return amount of data written
116                            if ((Uint32)bytesWritten == size)
117                            {
118                                return totalBytesWritten;
119                            }
120                            // If data has been written partially, we resume writing data
121                            // this also accounts for the case of a signal interrupt
122                            // (i.e. errno = EINTR)
123                            if (bytesWritten > 0)
124                            {
125                                size -= bytesWritten;
126                                ptr = (void *)((char *)ptr + bytesWritten);
127                                continue;
128                            }
129                            // Something went wrong
130                            if (bytesWritten == PEGASUS_SOCKET_ERROR)
131 marek         1.24         {
132                                // if we already waited for the socket to get ready, bail out
133                                if( socketTimedOut ) return bytesWritten;
134                    #ifdef PEGASUS_OS_TYPE_WINDOWS
135                                if (WSAGetLastError() == WSAEWOULDBLOCK)
136                    #else
137                                if (errno == EAGAIN || errno == EWOULDBLOCK)
138                    #endif
139                                {
140                                    fd_set fdwrite;
141                                     // max. timeout seconds waiting for the socket to get ready
142                                    struct timeval tv = { socketWriteTimeout, 0 };
143                                    FD_ZERO(&fdwrite);
144                                    FD_SET(socket, &fdwrite);
145                                    selreturn = select(FD_SETSIZE, NULL, &fdwrite, NULL, &tv);
146                                    if (selreturn == 0) socketTimedOut = true; // ran out of time
147                                    continue;            
148                                }
149                                return bytesWritten;
150                            }
151                        }
152 marek         1.24 }
153                    
154 mike          1.23 void Socket::close(SocketHandle socket)
155 mike          1.2  {
156 mike          1.23     if (socket != -1)
157                        {
158                    #ifdef PEGASUS_OS_TYPE_WINDOWS
159                    	if(!closesocket(socket)) 
160                    	    socket = -1;
161                    #else
162                    	int status;
163                    	PEGASUS_RETRY_SYSTEM_CALL(::close(socket), status);
164                    
165                    	if (status == 0)
166                    	    socket = -1;
167                    #endif
168                        }
169 mike          1.2  }
170                    
171 mike          1.23 void Socket::enableBlocking(SocketHandle socket)
172 mike          1.2  {
173                    #ifdef PEGASUS_OS_TYPE_WINDOWS
174                        unsigned long flag = 0;
175                        ioctlsocket(socket, FIONBIO, &flag);
176                    #else
177                        int flags = fcntl(socket, F_GETFL, 0);
178                        flags &= ~O_NONBLOCK;
179                        fcntl(socket, F_SETFL, flags);
180                    #endif
181                    }
182                    
183 mike          1.23 void Socket::disableBlocking(SocketHandle socket)
184 mike          1.2  {
185                    #ifdef PEGASUS_OS_TYPE_WINDOWS
186                        unsigned long flag = 1;
187                        ioctlsocket(socket, FIONBIO, &flag);
188                    #else
189                        int flags = fcntl(socket, F_GETFL, 0);
190                        flags |= O_NONBLOCK;
191                        fcntl(socket, F_SETFL, flags);
192                    #endif
193                    }
194                    
195                    void Socket::initializeInterface()
196                    {
197                    #ifdef PEGASUS_OS_TYPE_WINDOWS
198                        if (_socketInterfaceRefCount == 0)
199                        {
200 david.dillard 1.20         WSADATA tmp;
201 mike          1.2  
202 mike          1.23 	if (WSAStartup(0x202, &tmp) == SOCKET_ERROR)
203                    	    WSACleanup();
204 mike          1.2      }
205                    
206                        _socketInterfaceRefCount++;
207                    #endif
208                    }
209                    
210                    void Socket::uninitializeInterface()
211                    {
212                    #ifdef PEGASUS_OS_TYPE_WINDOWS
213                        _socketInterfaceRefCount--;
214                    
215                        if (_socketInterfaceRefCount == 0)
216 david.dillard 1.20         WSACleanup();
217 mike          1.2  #endif
218                    }
219                    
220 thilo.boehm   1.25 //------------------------------------------------------------------------------
221                    //
222                    // _setTCPNoDelay()
223                    //
224                    //------------------------------------------------------------------------------
225                    
226                    inline void _setTCPNoDelay(SocketHandle socket)
227                    {
228                        // This function disables "Nagle's Algorithm" also known as "the TCP delay
229                        // algorithm", which causes read operations to obtain whatever data is
230                        // already in the input queue and then wait a little longer to see if 
231                        // more data arrives. This algorithm optimizes the case in which data is 
232                        // sent in only one direction but severely impairs performance of round 
233                        // trip servers. Disabling TCP delay is a standard technique for round 
234                        // trip servers.
235                    
236                       int opt = 1;
237                       setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (char*)&opt, sizeof(opt));
238                    }
239                    //------------------------------------------------------------------------------
240                    //
241 thilo.boehm   1.25 // _setInformIfNewTCPIP()
242                    //
243                    //------------------------------------------------------------------------------
244                    inline void _setInformIfNewTCPIP(SocketHandle socket)
245                    {
246                    #ifdef PEGASUS_OS_ZOS
247                       // This function enables the notification of the CIM Server that a new
248                       // TCPIP transport layer is active. This is needed to be aware of a 
249                       // restart of the transport layer. When this option is in effect,
250                       // the accetp(), select(), and read() request will receive an errno=EIO.
251                       // Once this happens, the socket should be closed and create a new.
252                       
253                       int NewTcpipOn = 1;
254                       setibmsockopt(socket,SOL_SOCKET,SO_EioIfNewTP,(char*)&NewTcpipOn,sizeof(NewTcpipOn));
255                    #endif
256                    }
257                    
258                    
259                    SocketHandle Socket::createSocket(int domain, int type, int protocol)
260                    {
261                        SocketHandle newSocket;
262 thilo.boehm   1.25 
263                        if( domain == AF_UNIX)
264                        {
265                            return(socket(domain,type,protocol));
266                        }
267                    
268                        bool sendTcpipMsg = true;
269                    
270                        while(1)
271                        {
272                    
273                            newSocket = socket(domain,type,protocol);
274                    
275                            // The program should wait for transport layer to become ready.
276                    
277                            if(newSocket == PEGASUS_INVALID_SOCKET && 
278                               getSocketError() == PEGASUS_NETWORK_TCPIP_TRYAGAIN )
279                            {
280                               if(sendTcpipMsg)
281                               {
282                                   Logger::put_l(Logger::STANDARD_LOG, System::CIMSERVER, Logger::INFORMATION,
283 thilo.boehm   1.25                              "Common.Socket.WAIT_FOR_TCPIP",
284                                                 "TCP/IP temporary unavailable.");
285                                   sendTcpipMsg=false;
286                               }
287                    
288                               System::sleep(30);
289                               continue;
290                            } else 
291                            {
292                               break;
293                            }
294                        } // wait for the transport layer become ready.
295                    
296                        // Is the socket in an unrecoverable error ?
297                        if (newSocket == PEGASUS_INVALID_SOCKET)
298                        {
299                            // return immediate
300                            return(PEGASUS_INVALID_SOCKET);
301                        } else {
302                            
303                            // set aditional socket options
304 thilo.boehm   1.25         _setTCPNoDelay(newSocket);
305                            _setInformIfNewTCPIP(newSocket);
306                    
307                            return(newSocket);            
308                        }
309                    
310                    }
311                    
312 mike          1.2  PEGASUS_NAMESPACE_END
313 mday          1.11 

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2