1 mike 1.2 //%/////////////////////////////////////////////////////////////////////////////
2 //
|
3 kumpf 1.4 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
|
4 mike 1.2 // The Open Group, Tivoli Systems
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
7 kumpf 1.4 // of this software and associated documentation files (the "Software"), to
8 // deal in the Software without restriction, including without limitation the
9 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
10 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
|
13 kumpf 1.4 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
14 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
15 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
16 kumpf 1.4 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
17 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
18 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
19 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 //
22 //==============================================================================
23 //
24 // Author: Mike Brasher (mbrasher@bmc.com)
25 //
26 // Modified By:
27 //
28 //%/////////////////////////////////////////////////////////////////////////////
29
30 #include "Socket.h"
31
32 #ifdef PEGASUS_OS_TYPE_WINDOWS
|
33 tony 1.9 #include <windows.h>
34 # ifndef _WINSOCKAPI_
35 # include <winsock2.h>
36 # endif
|
37 mike 1.2 #else
38 # include <cctype>
|
39 chuck 1.5 #ifndef PEGASUS_OS_OS400
40 # include <unistd.h>
41 #else
|
42 chuck 1.6 # include <Pegasus/Common/OS400ConvertChar.h>
|
43 chuck 1.5 # include <unistd.cleinc>
44 #endif
|
45 marek 1.7 # include <string.h> // added by rk for memcpy
|
46 mike 1.2 # include <cstdlib>
47 # include <errno.h>
48 # include <fcntl.h>
49 # include <netdb.h>
50 # include <netinet/in.h>
51 # include <arpa/inet.h>
52 # include <sys/socket.h>
|
53 mday 1.9.4.1 # include <errno.h>
|
54 mike 1.2 #endif
55
|
56 mday 1.9.4.1 #include <Pegasus/Common/Sharable.h>
|
57 mike 1.2 PEGASUS_NAMESPACE_BEGIN
58
59 static Uint32 _socketInterfaceRefCount = 0;
60
61 Sint32 Socket::read(Sint32 socket, void* ptr, Uint32 size)
62 {
63 #ifdef PEGASUS_OS_TYPE_WINDOWS
64 return ::recv(socket, (char*)ptr, size, 0);
65 #elif defined(PEGASUS_OS_ZOS)
66 int i=::read(socket, (char*)ptr, size);
|
67 marek 1.8 #ifdef PEGASUS_HAVE_EBCDIC
|
68 mike 1.2 __atoe_l((char *)ptr,size);
|
69 marek 1.8 #endif
|
70 mike 1.2 return i;
|
71 chuck 1.6 #elif defined(PEGASUS_OS_OS400)
72 int i=::read(socket, (char*)ptr, size);
73 AtoE((char *)ptr, size);
74 return i;
|
75 mike 1.2 #else
|
76 mday 1.9.4.2
77 #if defined (__GNUC__)
78 int ccode = TEMP_FAILURE_RETRY(::read(socket, (char*)ptr, size));
79 return ccode;
80 #else
|
81 mike 1.2 return ::read(socket, (char*)ptr, size);
82 #endif
|
83 mday 1.9.4.2 #endif
|
84 mike 1.2 }
85
86 Sint32 Socket::write(Sint32 socket, const void* ptr, Uint32 size)
87 {
88 #ifdef PEGASUS_OS_TYPE_WINDOWS
89 return ::send(socket, (const char*)ptr, size, 0);
90 #elif defined(PEGASUS_OS_ZOS)
91 char * ptr2 = (char *)malloc(size);
92 int i;
93 memcpy(ptr2,ptr,size);
|
94 marek 1.8 #ifdef PEGASUS_HAVE_EBCDIC
|
95 mike 1.2 __etoa_l(ptr2,size);
|
96 marek 1.8 #endif
|
97 chuck 1.6 i = ::write(socket, ptr2, size);
98 free(ptr2);
99 return i;
100 #elif defined(PEGASUS_OS_OS400)
101 char * ptr2 = (char *)malloc(size);
102 int i;
103 memcpy(ptr2,ptr,size);
104 EtoA(ptr2,size);
|
105 mike 1.2 i = ::write(socket, ptr2, size);
106 free(ptr2);
107 return i;
108 #else
|
109 mday 1.9.4.2 #if (__GNUC__)
110 int ccode = TEMP_FAILURE_RETRY(::write(socket, (char*)ptr, size));
111 return ccode;
112 #else
|
113 mike 1.2 return ::write(socket, (char*)ptr, size);
114 #endif
|
115 mday 1.9.4.2 #endif
|
116 mike 1.2 }
117
118 void Socket::close(Sint32 socket)
119 {
120 #ifdef PEGASUS_OS_TYPE_WINDOWS
121 closesocket(socket);
122 #else
|
123 mday 1.9.4.2 #if (__GNUC__)
124 TEMP_FAILURE_RETRY(::close(socket));
125 #else
|
126 mike 1.2 ::close(socket);
127 #endif
|
128 mday 1.9.4.2 #endif
|
129 mike 1.2 }
130
|
131 mday 1.9.4.4 int Socket::close2(Sint32 socket)
132 {
133 #ifdef PEGASUS_OS_TYPE_WINDOWS
134 return closesocket(socket);
135 #else
136 #if (__GNUC__)
137 int ccode = TEMP_FAILURE_RETRY(::close(socket));
138 return ccode;
139 #else
140 return ::close(socket);
141 #endif
142 #endif
143 }
144
145
|
146 mike 1.2 void Socket::enableBlocking(Sint32 socket)
147 {
148 #ifdef PEGASUS_OS_TYPE_WINDOWS
149 unsigned long flag = 0;
150 ioctlsocket(socket, FIONBIO, &flag);
151 #else
152 int flags = fcntl(socket, F_GETFL, 0);
153 flags &= ~O_NONBLOCK;
154 fcntl(socket, F_SETFL, flags);
155 #endif
156 }
157
|
158 mday 1.9.4.4 int Socket::enableBlocking2(Sint32 socket)
159 {
160 #ifdef PEGASUS_OS_TYPE_WINDOWS
161 unsigned long flag = 0;
162 return ioctlsocket(socket, FIONBIO, &flag);
163 #else
164 int flags = fcntl(socket, F_GETFL, 0);
165 flags &= ~O_NONBLOCK;
166 return fcntl(socket, F_SETFL, flags);
167 #endif
168 }
169
|
170 mike 1.2 void Socket::disableBlocking(Sint32 socket)
171 {
172 #ifdef PEGASUS_OS_TYPE_WINDOWS
173 unsigned long flag = 1;
174 ioctlsocket(socket, FIONBIO, &flag);
175 #else
176 int flags = fcntl(socket, F_GETFL, 0);
177 flags |= O_NONBLOCK;
178 fcntl(socket, F_SETFL, flags);
179 #endif
180 }
181
|
182 mday 1.9.4.4 int Socket::disableBlocking2(Sint32 socket)
183 {
184 #ifdef PEGASUS_OS_TYPE_WINDOWS
185 unsigned long flag = 1;
186 return ioctlsocket(socket, FIONBIO, &flag);
187 #else
188 int flags = fcntl(socket, F_GETFL, 0);
189 flags |= O_NONBLOCK;
190 return fcntl(socket, F_SETFL, flags);
191 #endif
192 }
193
|
194 mike 1.2 void Socket::initializeInterface()
195 {
196 #ifdef PEGASUS_OS_TYPE_WINDOWS
197 if (_socketInterfaceRefCount == 0)
198 {
199 WSADATA tmp;
200
201 if (WSAStartup(0x202, &tmp) == SOCKET_ERROR)
202 WSACleanup();
203 }
204
205 _socketInterfaceRefCount++;
206 #endif
207 }
208
209 void Socket::uninitializeInterface()
210 {
211 #ifdef PEGASUS_OS_TYPE_WINDOWS
212 _socketInterfaceRefCount--;
213
214 if (_socketInterfaceRefCount == 0)
215 mike 1.2 WSACleanup();
216 #endif
217 }
|
218 mday 1.9.4.1
219
220 class abstract_socket : public Sharable
221 {
222 public:
223 abstract_socket(void) { }
224 virtual ~abstract_socket(void){ }
225
226 virtual operator Sint32() const = 0;
227 virtual int socket(int sock_type, int sock_style, int sock_protocol, void *ssl_context = 0) = 0;
228
229 virtual Sint32 read(void* ptr, Uint32 size) = 0;
230 virtual Sint32 write(const void* ptr, Uint32 size) = 0;
231 virtual int close(void) = 0;
|
232 mday 1.9.4.4 virtual int enableBlocking(void) = 0;
233 virtual int disableBlocking(void) = 0;
|
234 mday 1.9.4.1
235 virtual int getsockname (struct sockaddr *addr, size_t *length_ptr) = 0;
236 virtual int bind (struct sockaddr *addr, size_t length) = 0;
237
238 // change size_t to size_t for ZOS and windows
239 virtual abstract_socket* accept(struct sockaddr *addr, size_t *length_ptr) = 0;
|
240 mday 1.9.4.4 virtual int connect (struct sockaddr *addr, size_t length) = 0;
|
241 mday 1.9.4.1 virtual int shutdown(int how) = 0;
242 virtual int listen(int q) = 0;
243 virtual int getpeername (struct sockaddr *addr, size_t *length_ptr) = 0;
244 virtual int send (void *buffer, size_t size, int flags) = 0;
245 virtual int recv (void *buffer, size_t size, int flags) = 0;
246 virtual int sendto(void *buffer, size_t size, int flags, struct sockaddr *addr, size_t length) = 0;
247 virtual int recvfrom(void *buffer, size_t size, int flags, struct sockaddr *addr, size_t *length_ptr) = 0;
248 virtual int setsockopt (int level, int optname, void *optval, size_t optlen) = 0;
249 virtual int getsockopt (int level, int optname, void *optval, size_t *optlen_ptr) = 0;
250
251 virtual Boolean incompleteReadOccurred(Sint32 retCode) = 0;
252 virtual Boolean is_secure(void) = 0;
253 virtual void set_close_on_exec(void) = 0;
254 virtual const char* get_err_string(void) = 0;
255
256 private:
257
258 abstract_socket(const abstract_socket& );
259 abstract_socket& operator=(const abstract_socket& );
260 };
261
262 mday 1.9.4.1
263 /**
|
264 mday 1.9.4.3 * internet socket class
265 * designed to be overriden by ssl_socket_rep and file_socket_rep
266 *
|
267 mday 1.9.4.1 */
268 class bsd_socket_rep : public abstract_socket
269 {
270 public:
271
272 /**
273 * map to pegasus_socket::sock_err
274 */
275
276 bsd_socket_rep(void);
277 virtual ~bsd_socket_rep(void);
|
278 mday 1.9.4.4 // used to allow the accept method to work
279 bsd_socket_rep(int sock);
280
|
281 mday 1.9.4.1 operator Sint32() const;
282 int socket(int sock_type, int sock_style, int sock_protocol, void *ssl_context = 0);
283
284 virtual Sint32 read(void* ptr, Uint32 size);
285 virtual Sint32 write(const void* ptr, Uint32 size);
286 virtual int close(void);
|
287 mday 1.9.4.4 int enableBlocking(void);
288 int disableBlocking(void);
|
289 mday 1.9.4.1
|
290 mday 1.9.4.4 virtual int getsockname (struct sockaddr *addr, size_t *length_ptr);
291 virtual int bind (struct sockaddr *addr, size_t length);
|
292 mday 1.9.4.1
293 // change size_t to size_t for ZOS and windows
294 virtual abstract_socket* accept(struct sockaddr *addr, size_t *length_ptr);
|
295 mday 1.9.4.4 virtual int connect (struct sockaddr *addr, size_t length);
296 virtual int shutdown(int how);
297 virtual int listen(int queue_len );
|
298 mday 1.9.4.1 int getpeername (struct sockaddr *addr, size_t *length_ptr);
299 virtual int send (void *buffer, size_t size, int flags);
300 virtual int recv (void *buffer, size_t size, int flags);
|
301 mday 1.9.4.4 virtual int sendto(void *buffer, size_t size, int flags, struct sockaddr *addr, size_t length);
302 virtual int recvfrom(void *buffer, size_t size, int flags, struct sockaddr *addr, size_t *length_ptr);
|
303 mday 1.9.4.1 int setsockopt (int level, int optname, void *optval, size_t optlen);
304 int getsockopt (int level, int optname, void *optval, size_t *optlen_ptr);
305
|
306 mday 1.9.4.4 virtual Boolean incompleteReadOccurred(Sint32 retCode);
|
307 mday 1.9.4.1 virtual Boolean is_secure(void);
308 void set_close_on_exec(void);
|
309 mday 1.9.4.4 virtual const char* get_err_string(void);
310
|
311 mday 1.9.4.1 private:
312
|
313 mday 1.9.4.4
314 bsd_socket_rep& operator=(const bsd_socket_rep& );
|
315 mday 1.9.4.1 // use to perform one-time initializion and destruction
316 struct _library_init
317 {
318 _library_init(void)
319 {
320 }
321 ~_library_init(void)
322 {
323 }
324 };
325
326 static struct _library_init _lib_init;
327
328 int _socket;
329 void *_ssl_context;
330 int _errno;
|
331 mday 1.9.4.4 char _strerr[256];
|
332 mday 1.9.4.1 };
333
334 #if defined(__GNUC__) && GCC_VERSION >= 30200
335 // TEMP_FAILURE_RETRY (expression)
336 #else
337
338 #endif
339
340
341 /**
342 * default constructor for an (uninitialized) bsd socket
343 */
344 bsd_socket_rep::bsd_socket_rep(void)
345 :_errno(0)
346 {
347 }
348
|
349 mday 1.9.4.4 bsd_socket_rep::bsd_socket_rep(int sock)
350 : _socket(sock)
351 {
352 }
353
|
354 mday 1.9.4.1
355 /**
356 * default destructor for bsd_socket_rep
357 *
358 */
359 bsd_socket_rep::~bsd_socket_rep(void)
360 {
361
362 }
363
364 int bsd_socket_rep::shutdown(int how)
365 {
|
366 mday 1.9.4.4 int ccode = ::shutdown(_socket, how);
367 if(ccode == -1)
368 _errno = errno;
369 return ccode;
|
370 mday 1.9.4.1 }
371
372 bsd_socket_rep::operator Sint32() const
373 {
374 return (Sint32)_socket;
375 }
376
377 int bsd_socket_rep::socket(int sock_type, int sock_style, int sock_protocol, void *ssl_context)
378 {
379 _socket = ::socket(sock_type, sock_style, sock_protocol);
380 if(-1 == _socket )
381 {
382 _errno = errno;
383 }
384 return _socket;
385 }
386
387
|
388 mday 1.9.4.2 Sint32 bsd_socket_rep::read(void* ptr, Uint32 size)
|
389 mday 1.9.4.1 {
|
390 mday 1.9.4.4 int ccode = Socket::read(_socket, ptr, size);
391 if(ccode == -1)
392 _errno = errno;
393 return ccode;
|
394 mday 1.9.4.3 }
395
396
397 Sint32 bsd_socket_rep::write(const void* ptr, Uint32 size)
398 {
|
399 mday 1.9.4.4 int ccode = Socket::write(_socket, ptr, size);
400 if(ccode == -1)
401 errno = _errno;
402 return ccode;
|
403 mday 1.9.4.3 }
404
405
406 int bsd_socket_rep::close(void)
407 {
|
408 mday 1.9.4.4 int ccode;
|
409 mday 1.9.4.3
|
410 mday 1.9.4.4 shutdown(2);
411 ccode = Socket::close2(_socket);
412 if(ccode == -1)
413 _errno = errno;
414 return ccode;
415 }
416
417
418
419 int bsd_socket_rep::enableBlocking(void)
420 {
421 return Socket::enableBlocking2(_socket);
422 }
423
424 int bsd_socket_rep::disableBlocking(void)
425 {
426 return Socket::disableBlocking2(_socket);
427 }
428
429 int bsd_socket_rep::getsockname (struct sockaddr *addr, size_t *length_ptr)
430 {
431 mday 1.9.4.4 int ccode = ::getsockname(_socket, addr, length_ptr);
432 if(ccode == -1)
433 _errno = errno;
434 return ccode;
435 }
436
437 /**
438 * default implementation allows reuseof address
439 * sockaddr structure needs to be fully initialized or call will fail
440 */
441 int bsd_socket_rep::bind (struct sockaddr *addr, size_t length)
442 {
443 int opt = 1;
444 int ccode = setsockopt(SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt));
445 if(ccode < 0)
446 {
447 _errno = errno;
448 return ccode;
449 }
450 return ::bind(_socket, addr, length);
451 }
452 mday 1.9.4.4
453 abstract_socket* bsd_socket_rep::accept(struct sockaddr *addr, size_t *length_ptr)
454 {
455 int new_sock = ::accept(_socket, addr, length_ptr);
456 if(new_sock == -1)
457 {
458 _errno = errno;
459 return 0;
460 }
461
462 bsd_socket_rep *rep = new bsd_socket_rep(new_sock);
463 // set the close-on-exec flag
464 rep->set_close_on_exec();
465 return rep;
466 }
467
468 int bsd_socket_rep::connect (struct sockaddr *addr, size_t length)
469 {
470 int ccode = ::connect(_socket, addr, length);
471 if(ccode == -1)
472 _errno = errno;
473 mday 1.9.4.4 return ccode;
474 }
475
476
477 int bsd_socket_rep::listen(int queue_len)
478 {
479 int ccode = ::listen(_socket, queue_len);
480 if(ccode == -1)
481 _errno = errno;
482 return ccode;
483 }
484
485
486 int bsd_socket_rep::getpeername (struct sockaddr *addr, size_t *length_ptr)
487 {
488 int ccode = ::getpeername(_socket, addr, length_ptr);
489 if(ccode == -1 )
490 _errno = errno;
491 return ccode;
492 }
493
494 mday 1.9.4.4 int bsd_socket_rep::send (void *buffer, size_t size, int flags)
495 {
496 int ccode = ::send(_socket, buffer, size, flags);
497 if(ccode == -1)
498 _errno = errno;
499 return ccode;
500 }
501
502
503 int bsd_socket_rep::recv (void *buffer, size_t size, int flags)
504 {
505 int ccode = ::recv(_socket, buffer, size, flags);
506 if(ccode == -1)
507 _errno = errno;
508 return ccode;
509 }
510
511 int bsd_socket_rep::sendto(void *buffer, size_t size, int flags, struct sockaddr *addr, size_t length)
512 {
513 int ccode = ::sendto(_socket, buffer, size, flags, addr, length);
514 if(ccode == -1)
515 mday 1.9.4.4 _errno = errno;
516 return ccode;
517 }
518
519
520 int bsd_socket_rep::recvfrom(void *buffer,
521 size_t size,
522 int flags,
523 struct sockaddr *addr,
524 size_t *length_ptr)
525 {
526 int ccode = ::recvfrom(_socket, buffer, size, flags, addr, length_ptr);
527 if(ccode == -1)
528 _errno = errno;
529 return ccode;
530 }
531
532 int bsd_socket_rep::setsockopt (int level, int optname, void *optval, size_t optlen)
533 {
534 int ccode = ::setsockopt(_socket, level, optname, optval, optlen);
535 if(ccode == -1)
536 mday 1.9.4.4 _errno = errno;
537 return ccode;
538 }
539
540
541 int bsd_socket_rep::getsockopt (int level, int optname, void *optval, size_t *optlen_ptr)
542 {
543 int ccode = ::getsockopt(_socket, level, optname, optval, optlen_ptr);
544 if(ccode == -1)
545 _errno = errno;
546 return ccode;
547 }
548
549
550 Boolean bsd_socket_rep::incompleteReadOccurred(Sint32 retCode)
551 {
552 return false;
553 }
554
555 Boolean bsd_socket_rep::is_secure(void)
556 {
557 mday 1.9.4.4 return false;
558 }
559
560 void bsd_socket_rep::set_close_on_exec(void)
561 {
562 int sock_flags;
563 if( (sock_flags = fcntl(_socket, F_GETFD, 0)) >= 0)
564 {
565 sock_flags |= FD_CLOEXEC;
566 fcntl(_socket, F_SETFD, sock_flags);
567 }
568 }
569
570
571 const char* bsd_socket_rep::get_err_string(void)
572 {
573 strncpy(_strerr, strerror(_errno), 255);
574 return _strerr;
|
575 mday 1.9.4.1 }
576
577
|
578 mike 1.2
579 PEGASUS_NAMESPACE_END
|
580 mday 1.9.4.4
|