BioInt  1.02.00
BioInt: An integrative biological object-oriented application framework and interpreter
BioSocketBuffer.h
Go to the documentation of this file.
00001 #ifndef BIOSOCKETBUFFER_H
00002 #define BIOSOCKETBUFFER_H
00003 
00004 #include <new>
00005 #include <streambuf>
00006 #include <memory>
00007 #include <cstdio>
00008 #include <cstring>
00009 
00010 #include "BioSocketBase.h"
00011 
00012 template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
00013 class BioBasicSocketBuffer : public std::basic_streambuf<_CharT, _Traits>
00014 {
00015 public:
00016         // Types:
00017         typedef _CharT                          char_type;
00018         typedef _Traits                         traits_type;
00019         typedef typename traits_type::int_type  int_type;
00020         typedef typename traits_type::pos_type  pos_type;
00021         typedef typename traits_type::off_type  off_type;
00022 
00023         typedef std::basic_streambuf<char_type, traits_type> __streambuf_type;
00024 
00025 protected:
00026 
00028         BioSocket _M_socket;
00029 
00031         char *_M_ibuffer, *_M_obuffer;
00032 
00034         int _M_buf_size;
00035 
00036 
00037 public:
00039         BioBasicSocketBuffer() :
00040                 _M_socket(BioSocket::invalid_socket)
00041         {
00042                 _M_buffer_init();
00043         }
00044 
00045         explicit BioBasicSocketBuffer(BioSocket sock_)
00046         :       _M_socket(sock_)
00047         {
00048                 _M_buffer_init();
00049         }
00050         
00051 
00053         explicit BioBasicSocketBuffer(const BioSocketAddressIn& _sin)
00054         :       _M_socket(BioSocket::invalid_socket)
00055         {
00056                 _M_buffer_init();
00057                 connect(_sin);
00058         }
00059         
00060 
00062         virtual ~BioBasicSocketBuffer()
00063         {
00064                 sync();
00065                 close();
00066                 _M_buffer_delete();
00067         }
00068 
00070         BioSocket socket() const
00071         throw()
00072         {
00073                return _M_socket;
00074         }
00075 
00076 
00078         void socket(BioSocket sock_)
00079         throw()
00080         {
00081                 _M_socket = sock_;
00082         }
00083         
00084         bool connect(const BioSocketAddressIn& _sin)
00085         throw ()
00086         {
00087                 if (_M_socket.fd == BioSocket::invalid_socket)
00088                         if (!_M_socket.create(  BioSocket::pf_inet,
00089                                                 BioSocket::sock_stream,
00090                                                 BioSocket::proto_ip))
00091                                 return false;
00092                                                 
00093                 return _M_socket.connect(_sin);
00094         }
00095         
00096         bool connect(const std::string& _addr, uint16_t _port)
00097         throw()
00098         {
00099                 BioSocketAddressIn _sin;
00100 
00101                 if (!_sin.ip(_addr))
00102                         if (!_sin.resolve(_addr))
00103                                 return false;
00104 
00105                 _sin.port(_port);
00106 
00107                 return connect(_sin);
00108         }
00109 
00110 
00111         BioBasicSocketBuffer* close()
00112         throw()
00113         {
00114                 bool _s = _M_socket.close();
00115                 _M_socket.fd = BioSocket::invalid_socket;
00116 
00117                 return  _s ? 0 : this;
00118         }
00119         
00120         bool can_read(uint32_t usec_=0, uint32_t sec_ = 0)
00121         throw (std::ios_base::failure)
00122         {
00123                 if (_M_socket.can_read(usec_, sec_))
00124                         return true;
00125                 if (_M_socket.error)
00126                         throw std::ios_base::failure("BioBasicSocketBuffer::can_read()");
00127                 return false;
00128         }
00129         
00130         bool can_write(uint32_t _usec=0, uint32_t _sec = 0)
00131         throw (std::ios_base::failure)
00132         {
00133                 if (_M_socket.can_write(_usec, _sec))
00134                         return true;
00135                 if (_M_socket.error)
00136                         throw std::ios_base::failure("BioBasicSocketBuffer::can_write");
00137                 return false;
00138         }
00139         
00140 
00141         bool is_connected() const
00142         throw()
00143         {
00144                 BioSocketAddressIn _sin;
00145                 if (!_M_socket.peername(_sin))
00146                         return false;
00147                 return true;
00148         }
00149 
00150 protected:
00151         // Common initialization code for both ctors goes here.
00152         void _M_buffer_init(int _sz = 1024)
00153         {
00154                 _M_buf_size = _sz;
00155                 _M_ibuffer = new char_type[ (_M_buf_size+1) * 2 ];
00156                 _M_obuffer = _M_ibuffer + _M_buf_size + 1;
00157 
00158                 this->setg(_M_ibuffer, _M_ibuffer + 1, _M_ibuffer + 1);
00159                 this->setp(_M_obuffer, _M_obuffer + _M_buf_size);
00160         }
00161         
00162         void _M_buffer_delete()
00163         {
00164                 delete[] _M_ibuffer;
00165         }
00166 
00167 
00169         virtual int_type underflow()
00170         {
00171                 *this->eback() = -1[this->gptr()];  // to allow putback operations
00172 
00173                 int result = _M_socket.recv(this->eback() + 1 , _M_buf_size);
00174 
00175                 if (result < 1)
00176                         return traits_type::eof();
00177 
00178                 this->setg(this->eback(), this->eback()+1, this->eback() + result + 1);
00179                 
00180                 return traits_type::to_int_type(*this->gptr());
00181         }
00182         
00183 
00185         virtual int showmanyc()
00186         {
00187                 unsigned long data;
00188                 if (!_M_socket.ioctl(BioSocket::fionread, data))
00189                         return -1;
00190                 return data;
00191         }
00192         
00193 
00195         virtual int_type overflow(int_type __c = traits_type::eof())
00196         {
00197                 char *s1 = this->pbase();
00198                 char *s2 = this->pptr();
00199                 
00200                 int num = s2-s1;
00201 
00202                 /* TODO (DanielKO#2#): Make overflow use socklibpp::sock::sendall() */
00203                 if (__c != traits_type::eof()) {
00204                         *this->pptr() = __c;
00205                         ++num;
00206                 }
00207                 
00208                 if (!num)
00209                         return traits_type::eof();
00210 
00211                 int result = _M_socket.send(s1, num);
00212 
00213                 if (_M_socket.error)
00214                         return traits_type::eof();
00215 
00216                 if (result != num)      // didn't write everything
00217                         memmove(
00218                         //std::memmove(
00219                                 s1,
00220                                 s1 + result,
00221                                 num - result);
00222 
00223                 this->setp(_M_obuffer, _M_obuffer + _M_buf_size);
00224 
00225                 return traits_type::to_int_type(num);
00226         }
00227 
00228 
00230         virtual int sync()
00231         {
00232                 while (this->pptr() > this->pbase())
00233                         if (overflow(traits_type::eof()) == traits_type::eof())
00234                                 return -1;
00235                                 
00236                 return 0;
00237         }
00238 
00239         virtual __streambuf_type* setbuf(char_type*, std::streamsize _n)
00240         {
00241                 if (_n<2)
00242                         return 0;
00243                 try {
00244                         _M_buffer_delete();
00245                         _M_buffer_init(_n);
00246                         return this;
00247                 }
00248                 catch(...)
00249                 {
00250                         return 0;
00251                 }
00252         }
00253 
00254 };
00255 
00256 
00258 typedef BioBasicSocketBuffer<char>     BioSocketBuffer;
00259 
00260 #endif
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Friends Defines