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
|