00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
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_;
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_;
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
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
00431
00432
00433
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
00504
00505
00506 Socket&
00507 Socket::
00508 operator<< (char n_)
00509 {
00510
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
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 (mask_ & O_RDONLY) {
00718 answer = "O_RDONLY|";
00719 }
00720 if (mask_ & O_WRONLY) {
00721 answer += "O_WRONLY|";
00722 }
00723 if (mask_ & O_RDWR) {
00724 answer += "O_RDWR|";
00725 }
00726 if (mask_ & O_APPEND) {
00727 answer += "O_APPEND|";
00728 }
00729 if (mask_ & O_NONBLOCK) {
00730 answer += "O_NONBLOCK|";
00731 }
00732 if (mask_ & O_SYNC) {
00733 answer += "O_SYNC|";
00734 }
00735
00736 if (mask_ & O_ASYNC) {
00737 answer += "O_ASYNC|";
00738 }
00739
00740 answer.erase (answer.end () - 1);
00741
00742 return answer;
00743 }