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
45 //------------------------------------------------------------------------------
46 //
47 // PEGASUS_RETRY_SYSTEM_CALL()
48 //
49 // This macro repeats the given system call until it returns something
50 // other than EINTR.
51 //
52 //------------------------------------------------------------------------------
|
53 mike 1.2
54 #ifdef PEGASUS_OS_TYPE_WINDOWS
|
55 mike 1.23 # define PEGASUS_RETRY_SYSTEM_CALL(EXPR, RESULT) RESULT = EXPR
56 #else
57 # define PEGASUS_RETRY_SYSTEM_CALL(EXPR, RESULT) \
58 while (((RESULT = (EXPR)) == -1) && (errno == EINTR))
|
59 mike 1.2 #endif
60
61 PEGASUS_NAMESPACE_BEGIN
62
63 static Uint32 _socketInterfaceRefCount = 0;
64
|
65 mike 1.23 Sint32 Socket::read(SocketHandle socket, void* ptr, Uint32 size)
|
66 mike 1.2 {
67 #ifdef PEGASUS_OS_TYPE_WINDOWS
68 return ::recv(socket, (char*)ptr, size, 0);
69 #else
|
70 mike 1.23 int status;
71 PEGASUS_RETRY_SYSTEM_CALL(::read(socket, (char*)ptr, size), status);
72 return status;
|
73 mday 1.11 #endif
|
74 mike 1.2 }
75
|
76 mike 1.23 Sint32 Socket::write(SocketHandle socket, const void* ptr, Uint32 size)
|
77 mike 1.2 {
78 #ifdef PEGASUS_OS_TYPE_WINDOWS
79 return ::send(socket, (const char*)ptr, size, 0);
80 #else
|
81 mike 1.23 int status;
82 PEGASUS_RETRY_SYSTEM_CALL(::write(socket, (char*)ptr, size), status);
83 return status;
|
84 mday 1.11 #endif
|
85 mike 1.2 }
86
|
87 marek 1.24 Sint32 Socket::timedWrite(SocketHandle socket,
88 const void* ptr,
89 Uint32 size,
90 Uint32 socketWriteTimeout)
91 {
92 Sint32 bytesWritten = 0;
93 Sint32 totalBytesWritten = 0;
94 Boolean socketTimedOut = false;
95 int selreturn = 0;
96 while (1)
97 {
98 #ifdef PEGASUS_OS_TYPE_WINDOWS
99 PEGASUS_RETRY_SYSTEM_CALL(
100 ::send(socket, (const char*)ptr, size, 0), bytesWritten);
101 #else
102 PEGASUS_RETRY_SYSTEM_CALL(
103 ::write(socket, (char*)ptr, size), bytesWritten);
104 #endif
105 // Some data written this cycle ?
106 // Add it to the total amount of written data.
107 if (bytesWritten > 0)
108 marek 1.24 {
109 totalBytesWritten += bytesWritten;
110 socketTimedOut = false;
111 }
112
113 // All data written ? return amount of data written
114 if ((Uint32)bytesWritten == size)
115 {
116 return totalBytesWritten;
117 }
118 // If data has been written partially, we resume writing data
119 // this also accounts for the case of a signal interrupt
120 // (i.e. errno = EINTR)
121 if (bytesWritten > 0)
122 {
123 size -= bytesWritten;
124 ptr = (void *)((char *)ptr + bytesWritten);
125 continue;
126 }
127 // Something went wrong
128 if (bytesWritten == PEGASUS_SOCKET_ERROR)
129 marek 1.24 {
130 // if we already waited for the socket to get ready, bail out
131 if( socketTimedOut ) return bytesWritten;
132 #ifdef PEGASUS_OS_TYPE_WINDOWS
133 if (WSAGetLastError() == WSAEWOULDBLOCK)
134 #else
135 if (errno == EAGAIN || errno == EWOULDBLOCK)
136 #endif
137 {
138 fd_set fdwrite;
139 // max. timeout seconds waiting for the socket to get ready
140 struct timeval tv = { socketWriteTimeout, 0 };
141 FD_ZERO(&fdwrite);
142 FD_SET(socket, &fdwrite);
143 selreturn = select(FD_SETSIZE, NULL, &fdwrite, NULL, &tv);
144 if (selreturn == 0) socketTimedOut = true; // ran out of time
145 continue;
146 }
147 return bytesWritten;
148 }
149 }
150 marek 1.24 }
151
|
152 mike 1.23 void Socket::close(SocketHandle socket)
|
153 mike 1.2 {
|
154 mike 1.23 if (socket != -1)
155 {
156 #ifdef PEGASUS_OS_TYPE_WINDOWS
157 if(!closesocket(socket))
158 socket = -1;
159 #else
160 int status;
161 PEGASUS_RETRY_SYSTEM_CALL(::close(socket), status);
162
163 if (status == 0)
164 socket = -1;
165 #endif
166 }
|
167 mike 1.2 }
168
|
169 mike 1.23 void Socket::enableBlocking(SocketHandle socket)
|
170 mike 1.2 {
171 #ifdef PEGASUS_OS_TYPE_WINDOWS
172 unsigned long flag = 0;
173 ioctlsocket(socket, FIONBIO, &flag);
174 #else
175 int flags = fcntl(socket, F_GETFL, 0);
176 flags &= ~O_NONBLOCK;
177 fcntl(socket, F_SETFL, flags);
178 #endif
179 }
180
|
181 mike 1.23 void Socket::disableBlocking(SocketHandle socket)
|
182 mike 1.2 {
183 #ifdef PEGASUS_OS_TYPE_WINDOWS
184 unsigned long flag = 1;
185 ioctlsocket(socket, FIONBIO, &flag);
186 #else
187 int flags = fcntl(socket, F_GETFL, 0);
188 flags |= O_NONBLOCK;
189 fcntl(socket, F_SETFL, flags);
190 #endif
191 }
192
193 void Socket::initializeInterface()
194 {
195 #ifdef PEGASUS_OS_TYPE_WINDOWS
196 if (_socketInterfaceRefCount == 0)
197 {
|
198 david.dillard 1.20 WSADATA tmp;
|
199 mike 1.2
|
200 mike 1.23 if (WSAStartup(0x202, &tmp) == SOCKET_ERROR)
201 WSACleanup();
|
202 mike 1.2 }
203
204 _socketInterfaceRefCount++;
205 #endif
206 }
207
208 void Socket::uninitializeInterface()
209 {
210 #ifdef PEGASUS_OS_TYPE_WINDOWS
211 _socketInterfaceRefCount--;
212
213 if (_socketInterfaceRefCount == 0)
|
214 david.dillard 1.20 WSACleanup();
|
215 mike 1.2 #endif
216 }
217
218 PEGASUS_NAMESPACE_END
|
219 mday 1.11
|