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