BioInt
1.02.00
BioInt: An integrative biological object-oriented application framework and interpreter
|
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