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 #include "assa/Socket.h"
00028 #include "assa/XDRHack.h"
00029
00030 using namespace ASSA;
00031
00032 const int ASSA::Socket::PGSIZE = 4096;
00033
00041 int
00042 Socket::
00043 getBytesAvail (void) const
00044 {
00045 trace_with_mask("Socket::getBytesAvail",SOCKTRACE);
00046
00047 Socket* This = (Socket*) this;
00048 int ba = 0;
00049 int ret = ioctl (m_fd, FIONREAD, &ba);
00050
00051 if (ret == -1) {
00052 EL((ERROR,"ioctl(2) failed with ret: %d\n", ret));
00053 return ret;
00054 }
00055 ba += This->rdbuf ()->in_avail ();
00056
00057 DL((SOCKTRACE,"%d bytes available for reading\n", ba));
00058 return ba;
00059 }
00060
00061 Socket&
00062 Socket::
00063 flush ()
00064 {
00065 if (good () && rdbuf ()) {
00066 if (rdbuf ()->pubsync () == EOF) {
00067 setstate (badbit);
00068 }
00069 }
00070 return (*this);
00071 }
00072
00073 int
00074 Socket::
00075 set_option (int level_, int optname_, int val_)
00076 {
00077 int ret = setsockopt (m_fd, level_, optname_, (const char*) &val_,
00078 sizeof (val_));
00079 if (ret < 0)
00080 setstate (Socket::failbit);
00081 return ret;
00082 }
00083
00084 int
00085 Socket::
00086 set_fd_options (int flags_)
00087 {
00088 int val;
00089 if ((val = fcntl (m_fd, F_GETFL, 0)) < 0) {
00090 return -1;
00091 }
00092 val |= flags_;
00093
00094 return (fcntl (m_fd, F_SETFL, val) < 0) ? -1 : 0;
00095 }
00096
00097 int
00098 Socket::
00099 clear_fd_options (int flags_)
00100 {
00101 int val;
00102 if ((val = fcntl (m_fd, F_GETFL, 0)) < 0) {
00103 return -1;
00104 }
00105 val &= ~flags_;
00106
00107 return (fcntl (m_fd, F_SETFL, val) < 0) ? -1 : 0;
00108 }
00109
00110 bool
00111 Socket::
00112 turnOptionOn (opt_t opt_)
00113 {
00114 trace_with_mask("Socket::turnOptionOn",SOCKTRACE);
00115
00116 if (blocking == opt_)
00117 return clear_fd_options (O_NONBLOCK);
00118
00119 if (nonblocking == opt_)
00120 return set_fd_options (O_NONBLOCK);
00121
00122 int optname;
00123 if (reuseaddr == opt_)
00124 optname = SO_REUSEADDR;
00125 else {
00126 EL((ERROR,"Invalid socket option\n"));
00127 return false;
00128 }
00129 return set_option (SOL_SOCKET, optname, 1) == 0;
00130 }
00131
00132 bool
00133 Socket::
00134 turnOptionOff (opt_t opt_)
00135 {
00136 trace_with_mask("Socket::turnOptionOff",SOCKTRACE);
00137
00138 if (blocking == opt_)
00139 return set_fd_options (O_NONBLOCK);
00140
00141 if (nonblocking == opt_)
00142 return clear_fd_options (O_NONBLOCK);
00143
00144 int optname;
00145 if (reuseaddr == opt_)
00146 optname = SO_REUSEADDR;
00147 else {
00148 EL((ERROR,"Invalid socket option\n"));
00149 return false;
00150 }
00151 return set_option (SOL_SOCKET, optname, 0) == 0;
00152 }
00153
00154 bool
00155 Socket::
00156 setOption (opt_t opt_, int arg_)
00157 {
00158 trace_with_mask("Socket::setOption(,)",SOCKTRACE);
00159 int optname;
00160
00161 if (nonblocking == opt_)
00162 return (arg_ == 1) ? set_fd_options (O_NONBLOCK)
00163 : clear_fd_options (O_NONBLOCK);
00164
00165 if (blocking == opt_)
00166 return (arg_ == 1) ? clear_fd_options (O_NONBLOCK)
00167 : set_fd_options (O_NONBLOCK);
00168
00169 if (rcvlowat == opt_) optname = SO_RCVLOWAT;
00170 else if (sndlowat == opt_) optname = SO_SNDLOWAT;
00171 else {
00172 EL((ERROR,"Invalid socket option\n"));
00173 return false;
00174 }
00175 return set_option (SOL_SOCKET, optname, arg_) == 0;
00176 }
00177
00178 int
00179 Socket::
00180 getOption (opt_t opt_) const
00181 {
00182 trace_with_mask("Socket::getOption",SOCKTRACE);
00183 int optval = 0;
00184
00185 if (nonblocking == opt_) {
00186 if ((optval = fcntl (m_fd, F_GETFL, 0)) < 0) {
00187 return -1;
00188 }
00189 return ((optval & O_NONBLOCK) == O_NONBLOCK ? 1 : 0);
00190 }
00191
00192 if (blocking == opt_) {
00193 if ((optval = fcntl (m_fd, F_GETFL, 0)) < 0) {
00194 return -1;
00195 }
00196 return ((optval & O_NONBLOCK) == O_NONBLOCK ? 0 : 1);
00197 }
00198
00199 int optname;
00200 int level = SOL_SOCKET;
00201 bool bin = false;
00202
00203 socklen_t len = sizeof (optval);
00204 int ret;
00205
00206 if (rcvlowat == opt_) {
00207 optname = SO_RCVLOWAT;
00208 }
00209 else if (sndlowat == opt_) {
00210 optname = SO_SNDLOWAT;
00211 }
00212 else if (reuseaddr == opt_) {
00213 optname = SO_REUSEADDR;
00214 bin = true;
00215 }
00216 else {
00217 EL((ERROR,"Invalid socket option\n"));
00218 return (-1);
00219 }
00220
00221 #ifndef __CYGWIN32__
00222 ret = getsockopt (m_fd, level, optname, (char*) &optval, &len);
00223 #else
00224 ret = getsockopt (m_fd, level, optname, (char*) &optval, (int*)&len);
00225 #endif
00226
00227 if (ret < 0) {
00228 return (-1);
00229 }
00230 if (bin) {
00231 return (ret == 0 ? 0 : 1);
00232 }
00233 return (ret);
00234 }
00235
00236 int
00237 Socket::
00238 ignore(int n_, int delim_)
00239 {
00240 trace_with_mask("Socket::ignore",SOCKTRACE);
00241 register int b;
00242 register int count = 0;
00243 register char c;
00244
00245 if (n_ == INT_MAX && delim_ == EOF) {
00246 char buf[PGSIZE];
00247 while ((b = read (buf, PGSIZE))) {
00248 count += b;
00249 }
00250 setstate (Socket::eofbit|Socket::failbit);
00251 return count;
00252 }
00253 for (; n_; n_--, count++) {
00254 if ( (b = read (&c, 1)) == 0 ) {
00255 setstate (Socket::eofbit|Socket::failbit);
00256 break;
00257 }
00258 if ( c == delim_ )
00259 break;
00260 }
00261 return count;
00262 }
00263
00264
00265
00266
00267
00287 Socket&
00288 Socket::
00289 operator>>(char& n_)
00290 {
00291
00292 int c = 0;
00293 int len = sizeof (int);
00294 XDR xdrs;
00295 xdrmem_create (&xdrs, (caddr_t) &c, len, XDR_DECODE);
00296
00297 if (read ((char* ) &c, len) == len) {
00298 xdr_char (&xdrs, &n_);
00299 }
00300 else {
00301 setstate (Socket::eofbit|Socket::failbit);
00302 }
00303 xdr_destroy(&xdrs);
00304 return *this;
00305 }
00306
00309 Socket&
00310 Socket::
00311 operator>> (std::string& s_)
00312 {
00313 char c = 0;
00314 size_t n = 0;
00315 s_ = "";
00316
00317 (*this) >> n;
00318
00319 if (n == 0) {
00320 return *this;
00321 }
00322 size_t len = n;
00323 while (len-- && read (&c, 1) == 1) {
00324 s_ += c;
00325 }
00326 ignore (4 - n % 4);
00327 return *this;
00328 }
00329
00330 Socket&
00331 Socket::
00332 operator>> (short& n_)
00333 {
00334 short val;
00335 if (read ((char*) &val, sizeof(short)) == sizeof(short)) {
00336 n_ = (short) ntohs ((short)val);
00337 }
00338 else {
00339 setstate (Socket::eofbit|Socket::failbit);
00340 }
00341 return *this;
00342 }
00343
00344 Socket&
00345 Socket::
00346 operator>> (unsigned short& n_)
00347 {
00348 u_short val;
00349 if (read ((char*) &val, sizeof(u_short)) == sizeof(u_short)) {
00350 n_ = (u_short) ntohs ((u_short)val);
00351 }
00352 else {
00353 setstate (Socket::eofbit|Socket::failbit);
00354 }
00355 return *this;
00356 }
00357
00358 #define LONGEST long
00359
00360
00361
00362
00363
00364
00365
00366 #define READ_INT(TYPE) \
00367 Socket& Socket::operator>>(TYPE& n_) \
00368 {\
00369 LONGEST val;\
00370 int typesz = sizeof(TYPE);\
00371 if (read ( (char* ) &val, typesz) == typesz) {\
00372 if (sizeof(int32_t) <= typesz) {\
00373 n_ = (TYPE) ntohl (val); \
00374 }\
00375 else {\
00376 if (Socket::is_little_endian ()) {\
00377 *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val)) );\
00378 *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val))+1);\
00379 }\
00380 else {\
00381 *((int32_t*)(&n_) ) = ntohl (*((int32_t*)(&val)) );\
00382 *((int32_t*)(&n_)+1) = ntohl (*((int32_t*)(&val))+1);\
00383 }\
00384 }\
00385 }\
00386 else {\
00387 setstate (Socket::eofbit|Socket::failbit);\
00388 }\
00389 return *this;\
00390 }
00391
00392 READ_INT(int);
00393 READ_INT(unsigned int);
00394 READ_INT(long);
00395 READ_INT(unsigned long);
00396
00397 Socket&
00398 Socket::
00399 operator>> (float& n_)
00400 {
00401 float val;
00402 XDR xdrs;
00403 xdrmem_create (&xdrs, (caddr_t) &val, sizeof(float), XDR_DECODE);
00404
00405 if (read ((char*) &val, sizeof(float)) == sizeof(float)) {
00406 xdr_float (&xdrs, &n_);
00407 }
00408 else {
00409 setstate (Socket::eofbit|Socket::failbit);
00410 }
00411 xdr_destroy (&xdrs);
00412 return *this;
00413 }
00414
00415 Socket&
00416 Socket::
00417 operator>> (double& n_)
00418 {
00419 double val = 0;
00420 XDR xdrs;
00421 xdrmem_create (&xdrs, (caddr_t) &val, sizeof(double), XDR_DECODE);
00422 if (read ((char*) &val, sizeof(double)) == sizeof(double)) {
00423 xdr_double (&xdrs, &n_);
00424 }
00425 else {
00426 setstate (Socket::eofbit|Socket::failbit);
00427 }
00428 xdr_destroy (&xdrs);
00429 return *this;
00430 }
00431
00432
00433
00434
00435
00436 Socket&
00437 Socket::
00438 operator<< (char n_)
00439 {
00440
00441
00442 int buf = 0;
00443 int len = sizeof (int);
00444 XDR xdrs;
00445
00446 xdrmem_create (&xdrs, (caddr_t) &buf, len, XDR_ENCODE);
00447 xdr_char (&xdrs, &n_);
00448
00449 if (write ((const char*) &buf, len) != len) {
00450 (Socket::eofbit|Socket::failbit);
00451 }
00452 xdr_destroy (&xdrs);
00453 return *this;
00454 }
00455
00474 Socket&
00475 Socket::
00476 operator<< (const std::string& s_)
00477 {
00478 static const char pad [4] = { 0, 0, 0, 0 };
00479
00480 (*this) << s_.length ();
00481 int ret = write (s_.c_str (), s_.length ());
00482 if ( ret != s_.length () ) {
00483 setstate (Socket::eofbit|Socket::failbit);
00484 }
00485 size_t r = 4 - s_.length() % 4;
00486 if (r) {
00487 if (write (pad, r) != r) {
00488 setstate (Socket::eofbit|Socket::failbit);
00489 }
00490 }
00491 return *this;
00492 }
00493
00494 Socket& Socket::
00495 operator<< (short n_)
00496 {
00497 short val = (short) htons((short)n_);
00498
00499 if (write ((const char*) &val, sizeof(short)) != sizeof(short))
00500 {
00501 setstate (Socket::eofbit|Socket::failbit);
00502 }
00503 return *this;
00504 }
00505
00506 Socket& Socket::
00507 operator<< (unsigned short n_)
00508 {
00509 u_short val = (u_short) htons((u_short)n_);
00510
00511 if (write ((const char*) &val, sizeof(u_short)) != sizeof(u_short))
00512 {
00513 setstate (Socket::eofbit|Socket::failbit);
00514 }
00515 return *this;
00516 }
00517
00518 #define WRITE_INT(TYPE) \
00519 Socket& Socket::operator<< (TYPE n_) \
00520 { \
00521 LONGEST val;\
00522 int typesz = sizeof(TYPE);\
00523 if (sizeof(int32_t) <= typesz) {\
00524 val = (TYPE) ntohl (n_); \
00525 }\
00526 else {\
00527 if (Socket::is_little_endian ()) {\
00528 *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_)) );\
00529 *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_))+1);\
00530 }\
00531 else {\
00532 *((int32_t*)(&val) ) = htonl (*((int32_t*)(&n_)) );\
00533 *((int32_t*)(&val)+1) = htonl (*((int32_t*)(&n_))+1);\
00534 }\
00535 }\
00536 if (write ((const char*) &val, typesz) != typesz) {\
00537 setstate (Socket::eofbit|Socket::failbit);\
00538 }\
00539 return *this;\
00540 }
00541
00542 WRITE_INT(int);
00543 WRITE_INT(unsigned int);
00544 WRITE_INT(long);
00545 WRITE_INT(unsigned long);
00546
00547 Socket&
00548 Socket::
00549 operator<< (float n_)
00550 {
00551 float buf, f = n_;
00552 XDR xdrs;
00553 xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(float), XDR_ENCODE);
00554 xdr_float (&xdrs, &f);
00555
00556 int ret = write ((const char*) &buf, sizeof(float));
00557 xdr_destroy (&xdrs);
00558 if ( ret != sizeof(float) ) {
00559 setstate (Socket::eofbit|Socket::failbit);
00560 }
00561 return *this;
00562 }
00563
00564 Socket&
00565 Socket::
00566 operator<< (double n_)
00567 {
00568 double buf, f = n_;
00569 XDR xdrs;
00570 xdrmem_create (&xdrs, (caddr_t) &buf, sizeof(double), XDR_ENCODE);
00571 xdr_double (&xdrs, &f);
00572
00573 int ret = write ((const char*) &buf, sizeof(double));
00574 xdr_destroy (&xdrs);
00575 if ( ret != sizeof(double) ) {
00576 setstate (Socket::eofbit|Socket::failbit);
00577 }
00578 return *this;
00579 }
00580
00581 void
00582 Socket::
00583 dumpState (void) const
00584 {
00585 trace_with_mask("Socket::dumpState",SOCKTRACE);
00586
00587 char state_set[] = "[ set]\n";
00588 char state_not_set[] = "[not set]\n";
00589
00590 std::ostringstream msg;
00591
00592 msg << "\n";
00593 msg << "\tTesting good() ....... ";
00594
00595 if (this->good ()) msg << state_set;
00596 else msg << state_not_set;
00597
00598 msg << "\tTesting eof() ........ ";
00599 if (this->eof ()) msg << state_set;
00600 else msg << state_not_set;
00601
00602 msg << "\tTesting fail() ....... ";
00603 if (this->fail ()) msg << state_set;
00604 else msg << state_not_set;
00605
00606 msg << "\tTesting bad() ........ ";
00607 if (this->bad ()) msg << state_set;
00608 else msg << state_not_set;
00609
00610 msg << "\tTesting !() .......... ";
00611 if ( !(*this) ) msg << state_set;
00612 else msg << state_not_set;
00613
00614 msg << "\tTesting void *() ..... ";
00615 if ( *this ) msg << state_set;
00616 else msg << state_not_set;
00617
00618 msg << "\tTesting nonblocking... ";
00619 if (getOption (nonblocking) == 1) msg << state_set;
00620 else msg << state_not_set;
00621
00622
00623 msg << std::ends;
00624
00625 DL((SOCKTRACE,"%s\n", msg.str ().c_str ()));
00626 }
00627
00628 bool
00629 Socket::
00630 is_little_endian ()
00631 {
00632 union {
00633 char c [sizeof (short)];
00634 short v;
00635 } endian_u;
00636
00637 endian_u.v = 256;
00638 return (endian_u.c [0] == 0);
00639 }