00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef SOCKBUF_H
00023 #define SOCKBUF_H
00024
00025
00029 #include <new>
00030 #include <streambuf>
00031 #include <memory>
00032
00033 #include "sockbase.h"
00034
00035 namespace socklibpp {
00036
00037
00038
00039
00040
00041
00052 template<typename _CharT, typename _Traits = std::char_traits<_CharT> >
00053 class basic_sockbuf : public std::basic_streambuf<_CharT, _Traits>
00054 {
00055 public:
00056
00057 typedef _CharT char_type;
00058 typedef _Traits traits_type;
00059 typedef typename traits_type::int_type int_type;
00060 typedef typename traits_type::pos_type pos_type;
00061 typedef typename traits_type::off_type off_type;
00062
00063 typedef std::basic_streambuf<char_type, traits_type> __streambuf_type;
00064
00065 protected:
00066
00068 sock _M_socket;
00069
00071 char *_M_ibuffer, *_M_obuffer;
00072
00074 int _M_buf_size;
00075
00076
00077 public:
00079 basic_sockbuf() :
00080 _M_socket(sock::invalid_socket)
00081 {
00082 _M_buffer_init();
00083 }
00084
00090 explicit
00091 basic_sockbuf(sock sock_)
00092 : _M_socket(sock_)
00093 {
00094 _M_buffer_init();
00095 }
00096
00097
00099 explicit
00100 basic_sockbuf(const addr_in& _sin)
00101 : _M_socket(sock::invalid_socket)
00102 {
00103 _M_buffer_init();
00104 connect(_sin);
00105 }
00106
00107
00109 virtual
00110 ~basic_sockbuf()
00111 {
00112 sync();
00113 close();
00114 _M_buffer_delete();
00115 }
00116
00118 sock
00119 socket() const
00120 throw()
00121 {
00122 return _M_socket;
00123 }
00124
00125
00127 void
00128 socket(sock sock_)
00129 throw()
00130 {
00131 _M_socket = sock_;
00132 }
00133
00134
00138 bool
00139 connect(const addr_in& _sin)
00140 throw ()
00141 {
00142 if (_M_socket.fd == sock::invalid_socket)
00143 if (!_M_socket.create( sock::pf_inet,
00144 sock::sock_stream,
00145 sock::proto_ip))
00146 return false;
00147
00148 return _M_socket.connect(_sin);
00149 }
00150
00151
00157 bool
00158 connect(const std::string& _addr, uint16_t _port)
00159 throw()
00160 {
00161 addr_in _sin;
00162
00163 if (!_sin.ip(_addr))
00164 if (!_sin.resolve(_addr))
00165 return false;
00166
00167 _sin.port(_port);
00168
00169 return connect(_sin);
00170 }
00171
00172
00174 basic_sockbuf*
00175 close()
00176 throw()
00177 {
00178 bool _s = _M_socket.close();
00179 _M_socket.fd = sock::invalid_socket;
00180
00181 return _s ? 0 : this;
00182 }
00183
00184
00193 bool can_read(uint32_t usec_=0, uint32_t sec_ = 0)
00194 throw (std::ios_base::failure)
00195 {
00196 if (_M_socket.can_read(usec_, sec_))
00197 return true;
00198 if (_M_socket.error)
00199 throw std::ios_base::failure("basic_sockbuf::can_read()");
00200 return false;
00201 }
00202
00203
00212 bool can_write(uint32_t _usec=0, uint32_t _sec = 0)
00213 throw (std::ios_base::failure)
00214 {
00215 if (_M_socket.can_write(_usec, _sec))
00216 return true;
00217 if (_M_socket.error)
00218 throw std::ios_base::failure("basic_sockbuf::can_write");
00219 return false;
00220 }
00221
00222
00224 bool is_connected() const
00225 throw()
00226 {
00227 addr_in _sin;
00228 if (!_M_socket.peername(_sin))
00229 return false;
00230 return true;
00231 }
00232
00233 protected:
00234
00235 void _M_buffer_init(int _sz = 1024)
00236 {
00237 _M_buf_size = _sz;
00238 _M_ibuffer = new char_type[ (_M_buf_size+1) * 2 ];
00239 _M_obuffer = _M_ibuffer + _M_buf_size + 1;
00240
00241 this->setg(_M_ibuffer, _M_ibuffer + 1, _M_ibuffer + 1);
00242 this->setp(_M_obuffer, _M_obuffer + _M_buf_size);
00243 }
00244
00245 void _M_buffer_delete()
00246 {
00247 delete[] _M_ibuffer;
00248 }
00249
00250
00252 virtual int_type
00253 underflow()
00254 {
00255 *this->eback() = -1[this->gptr()];
00256
00257 int result = _M_socket.recv(this->eback() + 1 , _M_buf_size);
00258
00259 if (result < 1)
00260 return traits_type::eof();
00261
00262 this->setg(this->eback(), this->eback()+1, this->eback() + result + 1);
00263
00264 return traits_type::to_int_type(*this->gptr());
00265 }
00266
00267
00269 virtual int
00270 showmanyc()
00271 {
00272 unsigned long data;
00273 if (!_M_socket.ioctl(sock::fionread, data))
00274 return -1;
00275 return data;
00276 }
00277
00278
00280 virtual int_type
00281 overflow(int_type __c = traits_type::eof())
00282 {
00283 char *s1 = this->pbase();
00284 char *s2 = this->pptr();
00285
00286 int num = s2-s1;
00287
00288
00289 if (__c != traits_type::eof()) {
00290 *this->pptr() = __c;
00291 ++num;
00292 }
00293
00294 if (!num)
00295 return traits_type::eof();
00296
00297 int result = _M_socket.send(s1, num);
00298
00299 if (_M_socket.error)
00300 return traits_type::eof();
00301
00302 if (result != num)
00303 std::memmove(
00304 s1,
00305 s1 + result,
00306 num - result);
00307
00308 this->setp(_M_obuffer, _M_obuffer + _M_buf_size);
00309
00310 return traits_type::to_int_type(num);
00311 }
00312
00313
00315 virtual int
00316 sync()
00317 {
00318 while (this->pptr() > this->pbase())
00319 if (overflow(traits_type::eof()) == traits_type::eof())
00320 return -1;
00321
00322 return 0;
00323 }
00324
00325
00335
00336 virtual __streambuf_type*
00337 setbuf(char_type*, std::streamsize _n)
00338 {
00339 if (_n<2)
00340 return 0;
00341 try {
00342 _M_buffer_delete();
00343 _M_buffer_init(_n);
00344 return this;
00345 }
00346 catch(...)
00347 {
00348 return 0;
00349 }
00350 }
00351
00352
00353
00354
00355
00356
00357
00358 };
00359
00360
00362 typedef basic_sockbuf<char> sockbuf;
00363
00364 }
00365
00366 #endif