libassa 3.5.0
|
00001 // -*- c++ -*- 00002 //------------------------------------------------------------------------------ 00003 // $Id: Socket.cpp,v 1.13 2006/09/24 17:35:33 vlg Exp $ 00004 //------------------------------------------------------------------------------ 00005 // Socket.C 00006 //------------------------------------------------------------------------------ 00007 // Copyright (c) 1999,2005 by Vladislav Grinchenko 00008 // 00009 // This library is free software; you can redistribute it and/or 00010 // modify it under the terms of the GNU Library General Public 00011 // License as published by the Free Software Foundation; either 00012 // version 2 of the License, or (at your option) any later version. 00013 //------------------------------------------------------------------------ 00014 // Created: 03/22/99 00015 //------------------------------------------------------------------------ 00016 00017 #include <sstream> 00018 #if defined (__FreeBSD__) || defined(__FreeBSD_kernel__) || defined (__CYGWIN32__) 00019 # include <sys/ioctl.h> 00020 #endif 00021 00022 #if defined (__NetBSD__) 00023 # include <sys/filio.h> 00024 # include <sys/ioctl.h> 00025 #endif 00026 00027 #if defined (WIN32) 00028 # define O_NONBLOCK 04000 00029 typedef unsigned int socklen_t; 00030 #endif 00031 00032 #include "assa/Socket.h" 00033 #include "assa/XDRHack.h" 00034 00035 using namespace ASSA; 00036 00037 const int ASSA::Socket::PGSIZE = 4096; 00038 00046 int 00047 Socket:: 00048 getBytesAvail (void) const 00049 { 00050 trace_with_mask("Socket::getBytesAvail",SOCKTRACE); 00051 00052 Socket* This = (Socket*) this; 00053 u_long ba = 0; 00054 int ret = 0; 00055 00056 #if defined(WIN32) 00057 ret = ioctlsocket (m_fd, FIONREAD, &ba); 00058 #else 00059 ret = ioctl (m_fd, FIONREAD, &ba); 00060 #endif 00061 00062 if (ret == -1) { 00063 EL((ASSAERR,"ioctl(2) failed with ret: %d\n", ret)); 00064 return ret; 00065 } 00066 ba += This->rdbuf ()->in_avail (); 00067 00068 DL((SOCKTRACE,"%ld bytes available for reading\n", ba)); 00069 return (int(ba)); 00070 } 00071 00072 Socket& 00073 Socket:: 00074 flush () 00075 { 00076 if (good () && rdbuf ()) { 00077 if (rdbuf ()->pubsync () == EOF) { 00078 setstate (badbit); 00079 } 00080 } 00081 return (*this); 00082 } 00083 00084 int 00085 Socket:: 00086 set_option (int level_, int optname_, int val_) 00087 { 00088 int ret = setsockopt (m_fd, 00089 level_, 00090 optname_, 00091 (const char*) &val_, 00092 sizeof (val_)); 00093 if (ret < 0) { 00094 setstate (Socket::failbit); 00095 } 00096 return ret; 00097 } 00098 00102 int 00103 Socket:: 00104 set_fd_options (long flags_) 00105 { 00106 trace_with_mask("Socket::set_fd_options",SOCKTRACE); 00107 int val; 00108 int ret; 00109 00110 #if defined (WIN32) 00111 00112 u_long set_nonblock = 1; 00113 if ((val = ioctlsocket (m_fd, FIONBIO, &set_nonblock)) == 0) { 00114 m_nonblocking = true; 00115 return 0; 00116 } 00117 return -1; 00118 00119 #else // POSIX/UNIX 00120 00121 if ((val = ::fcntl (m_fd, F_GETFL, 0)) < 0) { 00122 return -1; 00123 } 00124 val |= flags_; // turn flags on 00125 00126 DL ((SOCKTRACE,"Set flags fcntl(%d, %s)\n", m_fd, 00127 decode_fcntl_flags (val).c_str ())); 00128 00129 ret = ::fcntl (m_fd, F_SETFL, val); 00130 00131 val = ::fcntl (m_fd, F_GETFL, 0); 00132 DL ((SOCKTRACE,"Flags are set to %s via fcntl(25)\n", 00133 decode_fcntl_flags (val).c_str ())); 00134 00135 return (ret); 00136 00137 #endif 00138 } 00139 00145 int 00146 Socket:: 00147 clear_fd_options (long flags_) 00148 { 00149 trace_with_mask("Socket::clear_fd_options",SOCKTRACE); 00150 long oldflags; 00151 long newflags; 00152 int ret; 00153 00154 #if defined (WIN32) 00155 00156 u_long set_block = 0; 00157 if ((ret = ioctlsocket (m_fd, FIONBIO, &set_block)) == 0) { 00158 m_nonblocking = false; 00159 return 0; 00160 } 00161 return -1; 00162 00163 #else 00164 00165 if ((oldflags = ::fcntl (m_fd, F_GETFL, 0)) < 0) { 00166 return -1; 00167 } 00168 newflags = oldflags & ~flags_; // clear flags 00169 00170 DL ((SOCKTRACE,"Set flags fcntl(%d, %s)\n", m_fd, 00171 decode_fcntl_flags (newflags).c_str ())); 00172 00173 ret = ::fcntl (m_fd, F_SETFL, newflags); 00174 00175 newflags = ::fcntl (m_fd, F_GETFL, 0); 00176 DL ((SOCKTRACE,"Flags are set to %s via fcntl(%d)\n", 00177 decode_fcntl_flags (newflags).c_str ())); 00178 00179 return (ret); 00180 #endif 00181 } 00182 00183 bool 00184 Socket:: 00185 turnOptionOn (opt_t opt_) 00186 { 00187 trace_with_mask("Socket::turnOptionOn",SOCKTRACE); 00188 00189 if (nonblocking == opt_) 00190 return set_fd_options (O_NONBLOCK); 00191 00192 int optname; 00193 if (reuseaddr == opt_) 00194 optname = SO_REUSEADDR; 00195 else { 00196 EL((ASSAERR,"Invalid socket option\n")); 00197 return false; 00198 } 00199 return set_option (SOL_SOCKET, optname, 1) == 0; 00200 } 00201 00202 bool 00203 Socket:: 00204 turnOptionOff (opt_t opt_) 00205 { 00206 trace_with_mask("Socket::turnOptionOff",SOCKTRACE); 00207 00208 if (nonblocking == opt_) 00209 return clear_fd_options (O_NONBLOCK); 00210 00211 int optname; 00212 if (reuseaddr == opt_) 00213 optname = SO_REUSEADDR; 00214 else { 00215 EL((ASSAERR,"Invalid socket option\n")); 00216 return false; 00217 } 00218 return set_option (SOL_SOCKET, optname, 0) == 0; 00219 } 00220 00221 bool 00222 Socket:: 00223 setOption (opt_t opt_, int arg_) 00224 { 00225 trace_with_mask("Socket::setOption(,)",SOCKTRACE); 00226 int optname; 00227 00228 if (nonblocking == opt_) { 00229 return (arg_ == 1) ? set_fd_options (O_NONBLOCK) 00230 : clear_fd_options (O_NONBLOCK); 00231 } 00232 00233 if (rcvlowat == opt_) { 00234 optname = SO_RCVLOWAT; 00235 } 00236 else if (sndlowat == opt_) { 00237 optname = SO_SNDLOWAT; 00238 } 00239 else { 00240 EL((ASSAERR,"Invalid socket option\n")); 00241 return false; 00242 } 00243 return set_option (SOL_SOCKET, optname, arg_) == 0; 00244 } 00245 00246 int 00247 Socket:: 00248 getOption (opt_t opt_) const 00249 { 00250 trace_with_mask("Socket::getOption",SOCKTRACE); 00251 int optval = 0; 00252 00253 if (nonblocking == opt_) 00254 { 00255 #if defined (WIN32) 00256 return (m_nonblocking ? 1 : 0); 00257 #else 00258 if ((optval = ::fcntl (m_fd, F_GETFL, 0)) < 0) { 00259 return -1; 00260 } 00261 return ((optval & O_NONBLOCK) == O_NONBLOCK ? 1 : 0); 00262 #endif 00263 } 00264 00265 int optname; 00266 int level = SOL_SOCKET; 00267 bool bin = false; 00268 00269 socklen_t len = sizeof (optval); 00270 int ret; 00271 00272 if (rcvlowat == opt_) { 00273 optname = SO_RCVLOWAT; 00274 } 00275 else if (sndlowat == opt_) { 00276 optname = SO_SNDLOWAT; 00277 } 00278 else if (reuseaddr == opt_) { 00279 optname = SO_REUSEADDR; 00280 bin = true; 00281 } 00282 else { 00283 EL((ASSAERR,"Invalid socket option\n")); 00284 return (-1); 00285 } 00286 00287 #if defined (__CYGWIN32__) || defined (WIN32) 00288 00289 ret = getsockopt (m_fd, level, optname, (char*) &optval, (int*)&len); 00290 00291 #else // posix/unix 00292 00293 ret = getsockopt (m_fd, level, optname, (char*) &optval, &len); 00294 00295 #endif 00296 00297 if (ret < 0) { 00298 return (-1); 00299 } 00300 if (bin) { 00301 return (ret == 0 ? 0 : 1); 00302 } 00303 return (ret); 00304 } 00305 00306 int 00307 Socket:: 00308 ignore(int n_, int delim_) 00309 { 00310 trace_with_mask("Socket::ignore",SOCKTRACE); 00311 register int b; 00312 register int count = 0; 00313 register char c; 00314 00315 if (n_ == INT_MAX && delim_ == EOF) { 00316 char buf[PGSIZE]; 00317 while ((b = read (buf, PGSIZE))) { 00318 count += b; 00319 } 00320 setstate (Socket::eofbit|Socket::failbit); 00321 return count; 00322 } 00323 for (; n_; n_--, count++) { 00324 if ( (b = read (&c, 1)) == 0 ) { 00325 setstate (Socket::eofbit|Socket::failbit); 00326 break; 00327 } 00328 if ( c == delim_ ) 00329 break; 00330 } 00331 return count; 00332 } 00333 00334 //----------------------------------------------------------------------------- 00335 // Input operators 00336 //----------------------------------------------------------------------------- 00337 00357 Socket& 00358 Socket:: 00359 operator>>(char& n_) 00360 { 00361 00362 int c = 0; 00363 int len = sizeof (int); 00364 XDR xdrs; 00365 xdrmem_create (&xdrs, (caddr_t) &c, len, XDR_DECODE); 00366 00367 if (read ((char* ) &c, len) == len) { 00368 xdr_char (&xdrs, &n_); 00369 } 00370 else { 00371 setstate (Socket::eofbit|Socket::failbit); 00372 } 00373 xdr_destroy(&xdrs); 00374 return *this; 00375 } 00376 00379 Socket& 00380 Socket:: 00381 operator>> (std::string& s_) 00382 { 00383 char c = 0; 00384 size_t n = 0; 00385 s_ = ""; 00386 00387 (*this) >> n; 00388 00389 if (n == 0) { 00390 return *this; 00391 } 00392 size_t len = n; 00393 while (len-- && read (&c, 1) == 1) { 00394 s_ += c; 00395 } 00396 ignore (4 - n % 4); 00397 return *this; 00398 } 00399 00400 Socket& 00401 Socket:: 00402 operator>> (short& n_) 00403 { 00404 short val; 00405 if (read ((char*) &val, sizeof(short)) == sizeof(short)) { 00406 n_ = (short) ntohs ((short)val); 00407 } 00408 else { 00409 setstate (Socket::eofbit|Socket::failbit); 00410 } 00411 return *this; 00412 } 00413 00414 Socket& 00415 Socket:: 00416 operator>> (unsigned short& n_) 00417 { 00418 u_short val; 00419 if (read ((char*) &val, sizeof(u_short)) == sizeof(u_short)) { 00420 n_ = (u_short) ntohs ((u_short)val); 00421 } 00422 else { 00423 setstate (Socket::eofbit|Socket::failbit); 00424 } 00425 return *this; 00426 } 00427 00428 #define LONGEST long 00429 00430 /* On 64-bit platforms, sizeof (long) = 8 bytes. 00431 * ntohl()/htonh() operats only on int32_t types which is 4 bytes long 00432 * everywhere. So, for 64-bit longs we need to process twice as much 00433 * and swapt data accordingly. 00434 */ 00435 00436 #define READ_INT(TYPE) \ 00437 Socket& Socket::operator>>(TYPE& n_) \ 00438 {\ 00439 LONGEST val;\ 00440 int typesz = sizeof(TYPE);\ 00441 if (read ( (char* ) &val, typesz) == typesz) {\ 00442 if (sizeof(int32_t) <= typesz) {\ 00443 n_ = (TYPE) ntohl (val); \ 00444 }\ 00445 else {\ 00446 if (Socket::is_little_endian ()) {\ 00447 *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val)) );\ 00448 *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val))+1);\ 00449 }\ 00450 else {\ 00451 *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val)) );\ 00452 *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val))+1);\ 00453 }\ 00454 }\ 00455 }\ 00456 else {\ 00457 setstate (Socket::eofbit|Socket::failbit);\ 00458 }\ 00459 return *this;\ 00460 } 00461 00462 READ_INT(int); 00463 READ_INT(unsigned int); 00464 READ_INT(long); 00465 READ_INT(unsigned long); 00466 00467 Socket& 00468 Socket:: 00469 operator>> (float& n_) 00470 { 00471 float val; 00472 XDR xdrs; 00473 xdrmem_create (&xdrs, (caddr_t) &val, sizeof(float), XDR_DECODE); 00474 00475 if (read ((char*) &val, sizeof(float)) == sizeof(float)) { 00476 xdr_float (&xdrs, &n_); 00477 } 00478 else { 00479 setstate (Socket::eofbit|Socket::failbit); 00480 } 00481 xdr_destroy (&xdrs); 00482 return *this; 00483 } 00484 00485 Socket& 00486 Socket:: 00487 operator>> (double& n_) 00488 { 00489 double val = 0; 00490 XDR xdrs; 00491 xdrmem_create (&xdrs, (caddr_t) &val, sizeof(double), XDR_DECODE); 00492 if (read ((char*) &val, sizeof(double)) == sizeof(double)) { 00493 xdr_double (&xdrs, &n_); 00494 } 00495 else { 00496 setstate (Socket::eofbit|Socket::failbit); 00497 } 00498 xdr_destroy (&xdrs); 00499 return *this; 00500 } 00501 00502 //----------------------------------------------------------------------------- 00503 // Output operators 00504 //----------------------------------------------------------------------------- 00505 00506 Socket& 00507 Socket:: 00508 operator<< (char n_) 00509 { 00510 /* See comment to operator>>(char n_) */ 00511 00512 int buf = 0; 00513 int len = sizeof (int); 00514 XDR xdrs; 00515 00516 xdrmem_create (&xdrs, (caddr_t) &buf, len, XDR_ENCODE); 00517 xdr_char (&xdrs, &n_); 00518 00519 if (write ((const char*) &buf, len) != len) { 00520 (Socket::eofbit|Socket::failbit); 00521 } 00522 xdr_destroy (&xdrs); 00523 return *this; 00524 } 00525 00544 Socket& 00545 Socket:: 00546 operator<< (const std::string& s_) 00547 { 00548 static const char pad [4] = { 0, 0, 0, 0 }; 00549 00550 (*this) << s_.length (); 00551 int ret = write (s_.c_str (), s_.length ()); 00552 if ( ret != s_.length () ) { 00553 setstate (Socket::eofbit|Socket::failbit); 00554 } 00555 size_t r = 4 - s_.length() % 4; 00556 if (r) { 00557 if (write (pad, r) != r) { 00558 setstate (Socket::eofbit|Socket::failbit); 00559 } 00560 } 00561 return *this; 00562 } 00563 00564 Socket& Socket:: 00565 operator<< (short n_) 00566 { 00567 short val = (short) htons((short)n_); 00568 00569 if (write ((const char*) &val, sizeof(short)) != sizeof(short)) 00570 { 00571 setstate (Socket::eofbit|Socket::failbit); 00572 } 00573 return *this; 00574 } 00575 00576 Socket& Socket:: 00577 operator<< (unsigned short n_) 00578 { 00579 u_short val = (u_short) htons((u_short)n_); 00580 00581 if (write ((const char*) &val, sizeof(u_short)) != sizeof(u_short)) 00582 { 00583 setstate (Socket::eofbit|Socket::failbit); 00584 } 00585 return *this; 00586 } 00587 00588 #define WRITE_INT(TYPE) \ 00589 Socket& Socket::operator<< (TYPE n_) \ 00590 { \ 00591 LONGEST val;\ 00592 int typesz = sizeof(TYPE);\ 00593 if (sizeof(int32_t) <= typesz) {\ 00594 val = (TYPE) ntohl (n_); \ 00595 }\ 00596 else {\ 00597 if (Socket::is_little_endian ()) {\ 00598 *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_)) );\ 00599 *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_))+1);\ 00600 }\ 00601 else {\ 00602 *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_)) );\ 00603 *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_))+1);\ 00604 }\ 00605 }\ 00606 if (write ((const char*) &val, typesz) != typesz) {\ 00607 setstate (Socket::eofbit|Socket::failbit);\ 00608 }\ 00609 return *this;\ 00610 } 00611 00612 WRITE_INT(int); 00613 WRITE_INT(unsigned int); 00614 WRITE_INT(long); 00615 WRITE_INT(unsigned long); 00616 00617 Socket& 00618 Socket:: 00619 operator<< (float n_) 00620 { 00621 float buf, f = n_; 00622 XDR xdrs; 00623 xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(float), XDR_ENCODE); 00624 xdr_float (&xdrs, &f); 00625 00626 int ret = write ((const char*) &buf, sizeof(float)); 00627 xdr_destroy (&xdrs); 00628 if ( ret != sizeof(float) ) { 00629 setstate (Socket::eofbit|Socket::failbit); 00630 } 00631 return *this; 00632 } 00633 00634 Socket& 00635 Socket:: 00636 operator<< (double n_) 00637 { 00638 double buf, f = n_; 00639 XDR xdrs; 00640 xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(double), XDR_ENCODE); 00641 xdr_double (&xdrs, &f); 00642 00643 int ret = write ((const char*) &buf, sizeof(double)); 00644 xdr_destroy (&xdrs); 00645 if ( ret != sizeof(double) ) { 00646 setstate (Socket::eofbit|Socket::failbit); 00647 } 00648 return *this; 00649 } 00650 00651 void 00652 Socket:: 00653 dumpState (void) const 00654 { 00655 trace_with_mask("Socket::dumpState",SOCKTRACE); 00656 00657 char state_set[] = "[ set]\n"; 00658 char state_not_set[] = "[not set]\n"; 00659 00660 std::ostringstream msg; 00661 00662 msg << "\n"; 00663 msg << "\tTesting good() ....... "; 00664 00665 if (this->good ()) msg << state_set; 00666 else msg << state_not_set; 00667 00668 msg << "\tTesting eof() ........ "; 00669 if (this->eof ()) msg << state_set; 00670 else msg << state_not_set; 00671 00672 msg << "\tTesting fail() ....... "; 00673 if (this->fail ()) msg << state_set; 00674 else msg << state_not_set; 00675 00676 msg << "\tTesting bad() ........ "; 00677 if (this->bad ()) msg << state_set; 00678 else msg << state_not_set; 00679 00680 msg << "\tTesting !() .......... "; 00681 if ( !(*this) ) msg << state_set; 00682 else msg << state_not_set; 00683 00684 msg << "\tTesting void *() ..... "; 00685 if ( *this ) msg << state_set; 00686 else msg << state_not_set; 00687 00688 msg << "\tTesting nonblocking... "; 00689 if (getOption (nonblocking) == 1) msg << state_set; 00690 else msg << state_not_set; 00691 00692 /*--- Terminate stream buffer ---*/ 00693 msg << std::ends; 00694 00695 DL((SOCKTRACE,"%s\n", msg.str ().c_str ())); 00696 } 00697 00698 bool 00699 Socket:: 00700 is_little_endian () 00701 { 00702 union { 00703 char c [sizeof (short)]; 00704 short v; 00705 } endian_u; 00706 00707 endian_u.v = 256; 00708 return (endian_u.c [0] == 0); 00709 } 00710 00711 string 00712 Socket:: 00713 decode_fcntl_flags (long mask_) 00714 { 00715 string answer; 00716 00717 #if !defined (WIN32) 00718 00719 if (mask_ & O_RDONLY) { 00720 answer = "O_RDONLY|"; // 000000 00721 } 00722 if (mask_ & O_WRONLY) { 00723 answer += "O_WRONLY|"; // 000001 00724 } 00725 if (mask_ & O_RDWR) { 00726 answer += "O_RDWR|"; // 000002 00727 } 00728 if (mask_ & O_APPEND) { 00729 answer += "O_APPEND|"; // 001000 00730 } 00731 if (mask_ & O_NONBLOCK) { 00732 answer += "O_NONBLOCK|";// 004000 00733 } 00734 if (mask_ & O_SYNC) { 00735 answer += "O_SYNC|"; // 010000 00736 } 00737 00738 if (mask_ & O_ASYNC) { // 020000 00739 answer += "O_ASYNC|"; 00740 } 00741 00742 answer.erase (answer.end () - 1); 00743 00744 #endif 00745 00746 return answer; 00747 }