00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00025 #ifndef SOCKETSTREAM_BASIC_SOCKETBUF_H
00026 #define SOCKETSTREAM_BASIC_SOCKETBUF_H 1
00027
00028 #include <socketstream/config.h>
00029
00030 #include <cerrno>
00031 #include <streambuf>
00032 #include <socketstream/basic_socket.h>
00033 #include <socketstream/address_factory.h>
00034
00035 #ifdef WIN32
00036 # define EWOULDBLOCK WSAEWOULDBLOCK
00037 #endif
00038
00039 #define SOCKETSTREAM_BUFSIZE 32
00040
00041 namespace ss {
00042
00049 template <typename _CharT, typename _Traits>
00050 class basic_socketbuf
00051 : public std::basic_streambuf<_CharT, _Traits>
00052 {
00053 public:
00054
00056
00063 typedef _CharT char_type;
00064 typedef _Traits traits_type;
00065
00066 typedef typename traits_type::int_type int_type;
00067 typedef typename traits_type::pos_type pos_type;
00068 typedef typename traits_type::off_type off_type;
00070
00071 typedef std::basic_streambuf<char_type, traits_type> __streambuf_type;
00072 typedef basic_socketbuf<char_type, traits_type> __socketbuf_type;
00073
00074 template <typename C, typename T>
00075 friend class basic_socketstream;
00076
00082 basic_socketbuf()
00083 : __streambuf_type(), _M_socket(), _M_flags(sockets_base::def::flag),
00084 _M_buf(0), _M_buf_size(SOCKETSTREAM_BUFSIZE),
00085 _M_put_buf_size(), _M_get_buf_size(),
00086 _M_buf_allocated(false),
00087 _M_open(false)
00088 {}
00089
00100 basic_socketbuf (sockets_base::family __f, sockets_base::style __s)
00101 : __streambuf_type(), _M_socket(__f, __s), _M_flags(sockets_base::def::flag),
00102 _M_buf(0), _M_buf_size(SOCKETSTREAM_BUFSIZE),
00103 _M_put_buf_size(), _M_get_buf_size(),
00104 _M_buf_allocated(false),
00105 _M_open(false)
00106 {}
00107
00111 virtual
00112 ~basic_socketbuf()
00113 { _M_destroy_internal_buffer(); }
00114
00123 template <typename AddressT>
00124 __socketbuf_type*
00125 connect (AddressT& __addr)
00126 {
00127 try
00128 {
00129 _M_socket.connect(&__addr, sizeof(__addr));
00130 _M_allocate_internal_buffer();
00131 }
00132 catch (const socket_exception& se)
00133 {
00134 switch (se.code())
00135 {
00136 case EWOULDBLOCK:
00137
00138 default:
00139 throw;
00140 }
00141 }
00142
00143 _M_open = true;
00144 return this;
00145 }
00146
00150 bool
00151 is_open () const throw ()
00152 {
00153 return _M_open;
00154 }
00155
00166 __socketbuf_type*
00167 shutdown (sockets_base::shutmode __mode = sockets_base::rw) throw ()
00168 {
00169 if (is_open())
00170 _M_socket.shutdown(__mode);
00171 _M_open = false;
00172 return this;
00173 }
00174
00180 basic_socket&
00181 socket ()
00182 {
00183 return _M_socket;
00184 }
00185
00191 sockets_base::flag
00192 setf (sockets_base::flag __f)
00193 {
00194 sockets_base::flag __old = _M_flags;
00195 _M_flags = __f;
00196 return __old;
00197 }
00198
00199 protected:
00200
00208 basic_socketbuf(basic_socket::descriptor_t descriptor)
00209 : __streambuf_type(), _M_socket(descriptor),
00210 _M_flags(sockets_base::def::flag),
00211 _M_buf(0), _M_buf_size(SOCKETSTREAM_BUFSIZE),
00212 _M_put_buf_size(), _M_get_buf_size(),
00213 _M_buf_allocated(false),
00214 _M_open(false)
00215 {}
00216
00228 virtual int_type
00229 underflow ()
00230 {
00231 int_type __ret = traits_type::eof();
00232 try
00233 {
00234 if (_M_get_buf_size > 0)
00235 {
00236 const size_t __buflen = _M_get_buf_size;
00237 int __num = _M_socket.receive(this->eback(), __buflen, _M_flags);
00238 if (__num > 0)
00239 {
00240 this->setg(this->eback(), this->eback(), this->eback() + __num);
00241 __ret = traits_type::to_int_type(*this->gptr());
00242 }
00243 }
00244 else
00245 {
00246 char_type c = __ret;
00247 if (_M_socket.receive(&c, 1, _M_flags) > 0)
00248 {
00249 __ret = traits_type::to_int_type(c);
00250 }
00251 }
00252 }
00253 catch (const socket_exception& e)
00254 {
00255 switch (e.code())
00256 {
00257 case EWOULDBLOCK:
00258
00259 case EINTR:
00260 default:
00261 throw;
00262 }
00263 }
00264 return __ret;
00265 }
00266
00277 virtual int_type
00278 uflow ()
00279 {
00280 int_type __ret = this->underflow();
00281 if (__ret != traits_type::eof() && _M_get_buf_size > 0)
00282 {
00283 this->gbump(1);
00284 }
00285 return __ret;
00286 }
00287
00300 virtual int_type
00301 overflow (int_type __c = traits_type::eof())
00302 {
00303 int_type __ret = traits_type::eof();
00304 const bool __testeof = traits_type::eq_int_type(__c, __ret);
00305 try
00306 {
00307 if (!__testeof)
00308 {
00309 *this->pptr() = traits_type::to_char_type(__c);
00310 this->pbump(1);
00311 }
00312 int __num = _M_socket.send(this->pbase(), this->pptr() - this->pbase(), _M_flags);
00313 if (__num > 0)
00314 {
00315 this->pbump(-__num);
00316 __ret = __c;
00317 }
00318 }
00319 catch (const socket_exception& e)
00320 {
00321 switch (e.code())
00322 {
00323 case EPIPE:
00324 return traits_type::eof();
00325 case EWOULDBLOCK:
00326
00327 case EINTR:
00328 default:
00329 throw;
00330 }
00331 }
00332 return __ret;
00333 }
00334
00341 virtual __streambuf_type*
00342 setbuf (char_type *__s, std::streamsize __n)
00343 {
00344 if (!this->is_open() && __s == 0 && __n == 0)
00345 {
00346 _M_buf_size = 1;
00347 }
00348 else if (__s && __n > 0)
00349 {
00350 _M_destroy_internal_buffer();
00351 _M_buf = __s;
00352 _M_buf_size = __n;
00353 _M_get_buf_size = _M_buf_size / 2;
00354 _M_put_buf_size = _M_buf_size - _M_get_buf_size;
00355 this->setp(_M_buf, _M_buf + _M_put_buf_size - 1);
00356 this->setg(_M_buf + _M_put_buf_size,
00357 _M_buf + _M_put_buf_size,
00358 _M_buf + _M_put_buf_size);
00359 }
00360 return this;
00361 }
00362
00366 virtual int
00367 sync ()
00368 {
00369 int __ret = 0;
00370 if (this->pbase() < this->pptr())
00371 {
00372 this->overflow();
00373 }
00374 return __ret;
00375 }
00376
00383 virtual std::streamsize
00384 showmanyc ()
00385 {
00386 std::streamsize __ret = -1;
00387 if (this->is_open())
00388 {
00389 __ret = this->egptr() - this->gptr();
00390 char_type c;
00391 __ret += _M_socket.receive(&c, 1, sockets_base::peek);
00392 }
00393 return __ret;
00394 }
00395
00405 virtual int_type
00406 pbackfail (int_type = traits_type::eof())
00407 {
00408 return traits_type::eof();
00409 }
00410
00411 private:
00412
00413 void
00414 _M_allocate_internal_buffer ()
00415 {
00416 if (!_M_buf_allocated && _M_buf_size)
00417 {
00418 _M_buf = new char_type[_M_buf_size];
00419 _M_buf_allocated = true;
00420 }
00421 _M_get_buf_size = _M_buf_size / 2;
00422 _M_put_buf_size = _M_buf_size - _M_get_buf_size;
00423 this->setp(_M_buf, _M_buf + _M_put_buf_size - 1);
00424 this->setg(_M_buf + _M_put_buf_size,
00425 _M_buf + _M_put_buf_size,
00426 _M_buf + _M_put_buf_size);
00427 }
00428
00429 void
00430 _M_destroy_internal_buffer () throw ()
00431 {
00432 if (_M_buf_allocated)
00433 {
00434 delete [] _M_buf;
00435 _M_buf = 0;
00436 _M_buf_allocated = false;
00437 }
00438 this->setp(0, 0);
00439 this->setg(0, 0, 0);
00440 }
00441
00442 private:
00443
00444 basic_socketbuf (basic_socketbuf<char_type, traits_type> const&);
00445 basic_socketbuf<char_type, traits_type>&
00446 operator= (basic_socketbuf<char_type, traits_type> const&);
00447
00448 basic_socket _M_socket;
00449
00450 sockets_base::flag _M_flags;
00451
00452 char_type* _M_buf;
00453 size_t _M_buf_size;
00454 size_t _M_put_buf_size;
00455 size_t _M_get_buf_size;
00456 bool _M_buf_allocated;
00457
00458 bool _M_open;
00459
00460 };
00461
00462 typedef basic_socketbuf<char, std::char_traits<char> > socketbuf;
00463
00464 }
00465
00466 #endif // SOCKETSTREAM_BASIC_SOCKETBUF_H