/build/buildd/libassa-3.4.1/assa/Socket.cpp

Go to the documentation of this file.
00001 // -*- c++ -*-
00002 //------------------------------------------------------------------------------
00003 // $Id: Socket.cpp,v 1.10 2006/03/14 15:51:16 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 #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_;      // turn flags on
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_; // turn flags off
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 //                         Input operators
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 /* On 64-bit platforms, sizeof (long) = 8 bytes. 
00361  * ntohl()/htonh() operats only on int32_t types which is 4 bytes long
00362  * everywhere. So, for 64-bit longs we need to process twice as much
00363  * and swapt data accordingly.
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 //                          Output operators
00434 //-----------------------------------------------------------------------------
00435 
00436 Socket& 
00437 Socket::
00438 operator<< (char n_) 
00439 { 
00440     /* See comment to operator>>(char n_) */
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     /*--- Terminate stream buffer ---*/
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 }

Generated on Wed Jun 21 15:58:58 2006 for libassa by  doxygen 1.4.6