11 #ifndef ASIO_BASIC_SOCKET_STREAMBUF_HPP 12 #define ASIO_BASIC_SOCKET_STREAMBUF_HPP 14 #if defined(_MSC_VER) && (_MSC_VER >= 1200) 16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) 18 #include "asio/detail/config.hpp" 20 #if !defined(ASIO_NO_IOSTREAM) 24 #include "asio/basic_socket.hpp" 25 #include "asio/basic_stream_socket.hpp" 26 #include "asio/detail/buffer_sequence_adapter.hpp" 27 #include "asio/detail/memory.hpp" 28 #include "asio/detail/throw_error.hpp" 29 #include "asio/io_context.hpp" 31 #if defined(ASIO_HAS_BOOST_DATE_TIME) \ 32 && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) 33 # include "asio/detail/deadline_timer_service.hpp" 34 #else // defined(ASIO_HAS_BOOST_DATE_TIME) 36 # include "asio/steady_timer.hpp" 37 #endif // defined(ASIO_HAS_BOOST_DATE_TIME) 40 #if !defined(ASIO_HAS_VARIADIC_TEMPLATES) 42 # include "asio/detail/variadic_templates.hpp" 57 # define ASIO_PRIVATE_CONNECT_DEF(n) \ 58 template <ASIO_VARIADIC_TPARAMS(n)> \ 59 basic_socket_streambuf* connect(ASIO_VARIADIC_BYVAL_PARAMS(n)) \ 62 typedef typename Protocol::resolver resolver_type; \ 63 resolver_type resolver(socket().get_executor()); \ 64 connect_to_endpoints( \ 65 resolver.resolve(ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \ 66 return !ec_ ? this : 0; \ 70 #endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) 72 #include "asio/detail/push_options.hpp" 83 : default_io_context_(ctx)
87 shared_ptr<io_context> default_io_context_;
99 : get_buffer_(buffer_size),
100 put_buffer_(buffer_size)
104 enum { buffer_size = 512 };
105 std::vector<char> get_buffer_;
106 std::vector<char> put_buffer_;
111 #if !defined(ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL) 112 #define ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL 115 template <
typename Protocol,
116 #if defined(ASIO_HAS_BOOST_DATE_TIME) \ 117 && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) 118 typename Clock = boost::posix_time::ptime,
119 typename WaitTraits = time_traits<Clock> >
120 #else // defined(ASIO_HAS_BOOST_DATE_TIME) 122 typename Clock = chrono::steady_clock,
124 #endif // defined(ASIO_HAS_BOOST_DATE_TIME) 128 #endif // !defined(ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL) 131 #if defined(GENERATING_DOCUMENTATION) 132 template <
typename Protocol,
133 typename Clock = chrono::steady_clock,
135 #else // defined(GENERATING_DOCUMENTATION) 136 template <
typename Protocol,
typename Clock,
typename WaitTraits>
137 #endif // defined(GENERATING_DOCUMENTATION) 139 :
public std::streambuf,
142 #if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) 144 #else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) 146 #endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION) 151 #if defined(ASIO_HAS_BOOST_DATE_TIME) \ 152 && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) 154 #else // defined(ASIO_HAS_BOOST_DATE_TIME) 157 #endif // defined(ASIO_HAS_BOOST_DATE_TIME) 170 #if defined(GENERATING_DOCUMENTATION) 171 typedef typename WaitTraits::time_type time_type;
175 typedef typename WaitTraits::time_point time_point;
178 typedef typename WaitTraits::duration_type duration_type;
181 typedef typename WaitTraits::duration duration;
183 # if !defined(ASIO_NO_DEPRECATED) 184 typedef typename traits_helper::time_type time_type;
185 typedef typename traits_helper::duration_type duration_type;
186 # endif // !defined(ASIO_NO_DEPRECATED) 187 typedef typename traits_helper::time_type time_point;
188 typedef typename traits_helper::duration_type duration;
195 expiry_time_(max_expiry_time())
200 #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 205 expiry_time_(max_expiry_time())
215 expiry_time_(other.expiry_time_)
217 get_buffer_.swap(other.get_buffer_);
218 put_buffer_.swap(other.put_buffer_);
219 setg(other.eback(), other.gptr(), other.egptr());
220 setp(other.pptr(), other.epptr());
222 other.expiry_time_ = max_expiry_time();
223 other.init_buffers();
230 socket() = std::move(other.socket());
231 detail::socket_streambuf_io_context::operator=(other);
233 expiry_time_ = other.expiry_time_;
234 get_buffer_.swap(other.get_buffer_);
235 put_buffer_.swap(other.put_buffer_);
236 setg(other.eback(), other.gptr(), other.egptr());
237 setp(other.pptr(), other.epptr());
239 other.expiry_time_ = max_expiry_time();
240 other.put_buffer_.resize(buffer_size);
241 other.init_buffers();
244 #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) 249 if (pptr() != pbase())
250 overflow(traits_type::eof());
264 this->connect_to_endpoints(&endpoint, &endpoint + 1);
265 return !ec_ ? this : 0;
268 #if defined(GENERATING_DOCUMENTATION) 278 template <
typename T1, ...,
typename TN>
280 #elif defined(ASIO_HAS_VARIADIC_TEMPLATES) 281 template <
typename... T>
285 typedef typename Protocol::resolver resolver_type;
286 resolver_type resolver(socket().get_executor());
287 connect_to_endpoints(resolver.resolve(x..., ec_));
288 return !ec_ ? this : 0;
291 ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CONNECT_DEF)
305 return !ec_ ? this : 0;
324 #if !defined(ASIO_NO_DEPRECATED) 346 #endif // !defined(ASIO_NO_DEPRECATED) 369 expiry_time_ = expiry_time;
383 expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
386 #if !defined(ASIO_NO_DEPRECATED) 394 return traits_helper::subtract(expires_at(), traits_helper::now());
409 expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
411 #endif // !defined(ASIO_NO_DEPRECATED) 416 #if defined(ASIO_WINDOWS_RUNTIME) 417 ec_ = asio::error::operation_not_supported;
418 return traits_type::eof();
419 #else // defined(ASIO_WINDOWS_RUNTIME) 420 if (gptr() != egptr())
421 return traits_type::eof();
426 if (traits_helper::less_than(expiry_time_, traits_helper::now()))
428 ec_ = asio::error::timed_out;
429 return traits_type::eof();
433 if (!socket().native_non_blocking())
434 socket().native_non_blocking(
true, ec_);
437 detail::signed_size_type
bytes = detail::socket_ops::recv(
438 socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
443 setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
444 &get_buffer_[0] + putback_max + bytes);
445 return traits_type::to_int_type(*gptr());
451 ec_ = asio::error::eof;
452 return traits_type::eof();
456 if (ec_ != asio::error::would_block
457 && ec_ != asio::error::try_again)
458 return traits_type::eof();
461 if (detail::socket_ops::poll_read(
462 socket().native_handle(), 0, timeout(), ec_) < 0)
463 return traits_type::eof();
465 #endif // defined(ASIO_WINDOWS_RUNTIME) 468 int_type overflow(int_type c)
470 #if defined(ASIO_WINDOWS_RUNTIME) 471 ec_ = asio::error::operation_not_supported;
472 return traits_type::eof();
473 #else // defined(ASIO_WINDOWS_RUNTIME) 474 char_type ch = traits_type::to_char_type(c);
478 if (put_buffer_.empty())
480 if (traits_type::eq_int_type(c, traits_type::eof()))
481 return traits_type::not_eof(c);
487 (pptr() - pbase()) *
sizeof(char_type));
490 while (output_buffer.
size() > 0)
493 if (traits_helper::less_than(expiry_time_, traits_helper::now()))
495 ec_ = asio::error::timed_out;
496 return traits_type::eof();
500 if (!socket().native_non_blocking())
501 socket().native_non_blocking(
true, ec_);
504 detail::signed_size_type
bytes = detail::socket_ops::send(
505 socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
510 output_buffer +=
static_cast<std::size_t
>(bytes);
515 if (ec_ != asio::error::would_block
516 && ec_ != asio::error::try_again)
517 return traits_type::eof();
520 if (detail::socket_ops::poll_write(
521 socket().native_handle(), 0, timeout(), ec_) < 0)
522 return traits_type::eof();
525 if (!put_buffer_.empty())
527 setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
530 if (traits_type::eq_int_type(c, traits_type::eof()))
531 return traits_type::not_eof(c);
539 #endif // defined(ASIO_WINDOWS_RUNTIME) 544 return overflow(traits_type::eof());
547 std::streambuf* setbuf(char_type* s, std::streamsize n)
549 if (pptr() == pbase() && s == 0 && n == 0)
568 setg(&get_buffer_[0],
569 &get_buffer_[0] + putback_max,
570 &get_buffer_[0] + putback_max);
572 if (put_buffer_.empty())
575 setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
580 int64_t msec = traits_helper::to_posix_duration(
581 traits_helper::subtract(expiry_time_,
582 traits_helper::now())).total_milliseconds();
583 if (msec > (std::numeric_limits<int>::max)())
584 msec = (std::numeric_limits<int>::max)();
587 return static_cast<int>(msec);
590 template <
typename Endpo
intSequence>
591 void connect_to_endpoints(
const EndpointSequence& endpoints)
593 this->connect_to_endpoints(endpoints.begin(), endpoints.end());
596 template <
typename Endpo
intIterator>
597 void connect_to_endpoints(EndpointIterator begin, EndpointIterator end)
599 #if defined(ASIO_WINDOWS_RUNTIME) 600 ec_ = asio::error::operation_not_supported;
601 #else // defined(ASIO_WINDOWS_RUNTIME) 605 ec_ = asio::error::not_found;
606 for (EndpointIterator i = begin; i != end; ++i)
609 if (traits_helper::less_than(expiry_time_, traits_helper::now()))
611 ec_ = asio::error::timed_out;
616 typename Protocol::endpoint ep(*i);
618 socket().open(ep.protocol(), ec_);
623 if (!socket().native_non_blocking())
624 socket().native_non_blocking(
true, ec_);
626 ep.data(), ep.size(), ec_);
633 if (ec_ != asio::error::in_progress
634 && ec_ != asio::error::would_block)
638 if (detail::socket_ops::poll_connect(
639 socket().native_handle(), timeout(), ec_) < 0)
643 int connect_error = 0;
644 size_t connect_error_len =
sizeof(connect_error);
645 if (detail::socket_ops::getsockopt(socket().native_handle(), 0,
646 SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec_)
647 == detail::socket_error_retval)
652 asio::error::get_system_category());
656 #endif // defined(ASIO_WINDOWS_RUNTIME) 660 static time_point max_expiry_time()
662 #if defined(ASIO_HAS_BOOST_DATE_TIME) \ 663 && defined(ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM) 664 return boost::posix_time::pos_infin;
665 #else // defined(ASIO_HAS_BOOST_DATE_TIME) 667 return (time_point::max)();
668 #endif // defined(ASIO_HAS_BOOST_DATE_TIME) 672 enum { putback_max = 8 };
674 time_point expiry_time_;
679 #include "asio/detail/pop_options.hpp" 681 #if !defined(ASIO_HAS_VARIADIC_TEMPLATES) 682 # undef ASIO_PRIVATE_CONNECT_DEF 683 #endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES) 685 #endif // !defined(ASIO_NO_IOSTREAM) 687 #endif // ASIO_BASIC_SOCKET_STREAMBUF_HPP Protocol protocol_type
The protocol type.
Definition: basic_socket_streambuf.hpp:162
const asio::error_code & puberror() const
(Deprecated: Use error().) Get the last error associated with the stream buffer.
Definition: basic_socket_streambuf.hpp:331
time_point expires_at() const
(Deprecated: Use expiry().) Get the stream buffer's expiry time as an absolute time.
Definition: basic_socket_streambuf.hpp:342
time_point expiry() const
Get the stream buffer's expiry time as an absolute time.
Definition: basic_socket_streambuf.hpp:353
Definition: basic_socket_streambuf.hpp:79
Holds a buffer that cannot be modified.
Definition: buffer.hpp:226
basic_socket< Protocol > & socket()
Get a reference to the underlying socket.
Definition: basic_socket_streambuf.hpp:309
Definition: blocking.hpp:208
Provides stream-oriented socket functionality.
Definition: basic_stream_socket.hpp:36
Definition: chrono_time_traits.hpp:34
duration expires_from_now() const
(Deprecated: Use expiry().) Get the stream buffer's expiry time relative to now.
Definition: basic_socket_streambuf.hpp:392
basic_socket_streambuf()
Construct a basic_socket_streambuf without establishing a connection.
Definition: basic_socket_streambuf.hpp:192
void expires_from_now(const duration &expiry_time)
(Deprecated: Use expires_after().) Set the stream buffer's expiry time relative to now...
Definition: basic_socket_streambuf.hpp:407
void expires_after(const duration &expiry_time)
Set the stream buffer's expiry time relative to now.
Definition: basic_socket_streambuf.hpp:381
std::size_t size() const ASIO_NOEXCEPT
Get the size of the memory range.
Definition: buffer.hpp:279
Provides core I/O functionality.
Definition: io_context.hpp:211
ASIO_MUTABLE_BUFFER buffer(const mutable_buffer &b) ASIO_NOEXCEPT
Create a new modifiable buffer from an existing buffer.
Definition: buffer.hpp:909
Definition: buffer_sequence_adapter.hpp:103
Protocol::endpoint endpoint_type
The endpoint type.
Definition: basic_socket_streambuf.hpp:165
Protocol::endpoint connect(basic_socket< Protocol, Executor > &s, const EndpointSequence &endpoints, typename enable_if< is_endpoint_sequence< EndpointSequence >::value >::type *=0)
Establishes a socket connection by trying each endpoint in a sequence.
Definition: connect.hpp:106
Wait traits suitable for use with the basic_waitable_timer class template.
Definition: netfwd.hpp:111
virtual ~basic_socket_streambuf()
Destructor flushes buffered data.
Definition: basic_socket_streambuf.hpp:247
Class to represent an error code value.
Definition: error_code.hpp:80
void expires_at(const time_point &expiry_time)
Set the stream buffer's expiry time as an absolute time.
Definition: basic_socket_streambuf.hpp:367
basic_socket_streambuf * connect(const endpoint_type &endpoint)
Establish a connection.
Definition: basic_socket_streambuf.hpp:260
Provides socket functionality.
Definition: basic_socket.hpp:52
Definition: basic_socket_streambuf.hpp:95
Iostream streambuf for a socket.
Definition: basic_socket_streambuf.hpp:126
Clock clock_type
The clock type.
Definition: basic_socket_streambuf.hpp:168
Definition: any_io_executor.hpp:28
basic_socket_streambuf * close()
Close the connection.
Definition: basic_socket_streambuf.hpp:299
const asio::error_code & error() const
Get the last error associated with the stream buffer.
Definition: basic_socket_streambuf.hpp:319
Definition: format.h:3611