]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/asio/basic_socket_streambuf.hpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / boost / asio / basic_socket_streambuf.hpp
1 //
2 // basic_socket_streambuf.hpp
3 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
4 //
5 // Copyright (c) 2003-2022 Christopher M. Kohlhoff (chris at kohlhoff dot com)
6 //
7 // Distributed under the Boost Software License, Version 1.0. (See accompanying
8 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
9 //
10
11 #ifndef BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
12 #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
13
14 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
15 # pragma once
16 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
17
18 #include <boost/asio/detail/config.hpp>
19
20 #if !defined(BOOST_ASIO_NO_IOSTREAM)
21
22 #include <streambuf>
23 #include <vector>
24 #include <boost/asio/basic_socket.hpp>
25 #include <boost/asio/basic_stream_socket.hpp>
26 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
27 #include <boost/asio/detail/memory.hpp>
28 #include <boost/asio/detail/throw_error.hpp>
29 #include <boost/asio/io_context.hpp>
30
31 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
32 && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
33 # include <boost/asio/detail/deadline_timer_service.hpp>
34 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
35 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
36 # include <boost/asio/steady_timer.hpp>
37 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
38 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
39
40 #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
41
42 # include <boost/asio/detail/variadic_templates.hpp>
43
44 // A macro that should expand to:
45 // template <typename T1, ..., typename Tn>
46 // basic_socket_streambuf* connect(T1 x1, ..., Tn xn)
47 // {
48 // init_buffers();
49 // typedef typename Protocol::resolver resolver_type;
50 // resolver_type resolver(socket().get_executor());
51 // connect_to_endpoints(
52 // resolver.resolve(x1, ..., xn, ec_));
53 // return !ec_ ? this : 0;
54 // }
55 // This macro should only persist within this file.
56
57 # define BOOST_ASIO_PRIVATE_CONNECT_DEF(n) \
58 template <BOOST_ASIO_VARIADIC_TPARAMS(n)> \
59 basic_socket_streambuf* connect(BOOST_ASIO_VARIADIC_BYVAL_PARAMS(n)) \
60 { \
61 init_buffers(); \
62 typedef typename Protocol::resolver resolver_type; \
63 resolver_type resolver(socket().get_executor()); \
64 connect_to_endpoints( \
65 resolver.resolve(BOOST_ASIO_VARIADIC_BYVAL_ARGS(n), ec_)); \
66 return !ec_ ? this : 0; \
67 } \
68 /**/
69
70 #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
71
72 #include <boost/asio/detail/push_options.hpp>
73
74 namespace boost {
75 namespace asio {
76 namespace detail {
77
78 // A separate base class is used to ensure that the io_context member is
79 // initialised prior to the basic_socket_streambuf's basic_socket base class.
80 class socket_streambuf_io_context
81 {
82 protected:
83 socket_streambuf_io_context(io_context* ctx)
84 : default_io_context_(ctx)
85 {
86 }
87
88 shared_ptr<io_context> default_io_context_;
89 };
90
91 // A separate base class is used to ensure that the dynamically allocated
92 // buffers are constructed prior to the basic_socket_streambuf's basic_socket
93 // base class. This makes moving the socket is the last potentially throwing
94 // step in the streambuf's move constructor, giving the constructor a strong
95 // exception safety guarantee.
96 class socket_streambuf_buffers
97 {
98 protected:
99 socket_streambuf_buffers()
100 : get_buffer_(buffer_size),
101 put_buffer_(buffer_size)
102 {
103 }
104
105 enum { buffer_size = 512 };
106 std::vector<char> get_buffer_;
107 std::vector<char> put_buffer_;
108 };
109
110 } // namespace detail
111
112 #if !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
113 #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL
114
115 // Forward declaration with defaulted arguments.
116 template <typename Protocol,
117 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
118 && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
119 typename Clock = boost::posix_time::ptime,
120 typename WaitTraits = time_traits<Clock> >
121 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
122 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
123 typename Clock = chrono::steady_clock,
124 typename WaitTraits = wait_traits<Clock> >
125 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
126 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
127 class basic_socket_streambuf;
128
129 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
130
131 /// Iostream streambuf for a socket.
132 #if defined(GENERATING_DOCUMENTATION)
133 template <typename Protocol,
134 typename Clock = chrono::steady_clock,
135 typename WaitTraits = wait_traits<Clock> >
136 #else // defined(GENERATING_DOCUMENTATION)
137 template <typename Protocol, typename Clock, typename WaitTraits>
138 #endif // defined(GENERATING_DOCUMENTATION)
139 class basic_socket_streambuf
140 : public std::streambuf,
141 private detail::socket_streambuf_io_context,
142 private detail::socket_streambuf_buffers,
143 #if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
144 private basic_socket<Protocol>
145 #else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
146 public basic_socket<Protocol>
147 #endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
148 {
149 private:
150 // These typedefs are intended keep this class's implementation independent
151 // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
152 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
153 && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
154 typedef WaitTraits traits_helper;
155 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
156 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
157 typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
158 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
159 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
160
161 public:
162 /// The protocol type.
163 typedef Protocol protocol_type;
164
165 /// The endpoint type.
166 typedef typename Protocol::endpoint endpoint_type;
167
168 /// The clock type.
169 typedef Clock clock_type;
170
171 #if defined(GENERATING_DOCUMENTATION)
172 /// (Deprecated: Use time_point.) The time type.
173 typedef typename WaitTraits::time_type time_type;
174
175 /// The time type.
176 typedef typename WaitTraits::time_point time_point;
177
178 /// (Deprecated: Use duration.) The duration type.
179 typedef typename WaitTraits::duration_type duration_type;
180
181 /// The duration type.
182 typedef typename WaitTraits::duration duration;
183 #else
184 # if !defined(BOOST_ASIO_NO_DEPRECATED)
185 typedef typename traits_helper::time_type time_type;
186 typedef typename traits_helper::duration_type duration_type;
187 # endif // !defined(BOOST_ASIO_NO_DEPRECATED)
188 typedef typename traits_helper::time_type time_point;
189 typedef typename traits_helper::duration_type duration;
190 #endif
191
192 /// Construct a basic_socket_streambuf without establishing a connection.
193 basic_socket_streambuf()
194 : detail::socket_streambuf_io_context(new io_context),
195 basic_socket<Protocol>(*default_io_context_),
196 expiry_time_(max_expiry_time())
197 {
198 init_buffers();
199 }
200
201 #if defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
202 /// Construct a basic_socket_streambuf from the supplied socket.
203 explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s)
204 : detail::socket_streambuf_io_context(0),
205 basic_socket<Protocol>(std::move(s)),
206 expiry_time_(max_expiry_time())
207 {
208 init_buffers();
209 }
210
211 /// Move-construct a basic_socket_streambuf from another.
212 basic_socket_streambuf(basic_socket_streambuf&& other)
213 : detail::socket_streambuf_io_context(other),
214 basic_socket<Protocol>(std::move(other.socket())),
215 ec_(other.ec_),
216 expiry_time_(other.expiry_time_)
217 {
218 get_buffer_.swap(other.get_buffer_);
219 put_buffer_.swap(other.put_buffer_);
220 setg(other.eback(), other.gptr(), other.egptr());
221 setp(other.pptr(), other.epptr());
222 other.ec_ = boost::system::error_code();
223 other.expiry_time_ = max_expiry_time();
224 other.init_buffers();
225 }
226
227 /// Move-assign a basic_socket_streambuf from another.
228 basic_socket_streambuf& operator=(basic_socket_streambuf&& other)
229 {
230 this->close();
231 socket() = std::move(other.socket());
232 detail::socket_streambuf_io_context::operator=(other);
233 ec_ = other.ec_;
234 expiry_time_ = other.expiry_time_;
235 get_buffer_.swap(other.get_buffer_);
236 put_buffer_.swap(other.put_buffer_);
237 setg(other.eback(), other.gptr(), other.egptr());
238 setp(other.pptr(), other.epptr());
239 other.ec_ = boost::system::error_code();
240 other.expiry_time_ = max_expiry_time();
241 other.put_buffer_.resize(buffer_size);
242 other.init_buffers();
243 return *this;
244 }
245 #endif // defined(BOOST_ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)
246
247 /// Destructor flushes buffered data.
248 virtual ~basic_socket_streambuf()
249 {
250 if (pptr() != pbase())
251 overflow(traits_type::eof());
252 }
253
254 /// Establish a connection.
255 /**
256 * This function establishes a connection to the specified endpoint.
257 *
258 * @return \c this if a connection was successfully established, a null
259 * pointer otherwise.
260 */
261 basic_socket_streambuf* connect(const endpoint_type& endpoint)
262 {
263 init_buffers();
264 ec_ = boost::system::error_code();
265 this->connect_to_endpoints(&endpoint, &endpoint + 1);
266 return !ec_ ? this : 0;
267 }
268
269 #if defined(GENERATING_DOCUMENTATION)
270 /// Establish a connection.
271 /**
272 * This function automatically establishes a connection based on the supplied
273 * resolver query parameters. The arguments are used to construct a resolver
274 * query object.
275 *
276 * @return \c this if a connection was successfully established, a null
277 * pointer otherwise.
278 */
279 template <typename T1, ..., typename TN>
280 basic_socket_streambuf* connect(T1 t1, ..., TN tn);
281 #elif defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
282 template <typename... T>
283 basic_socket_streambuf* connect(T... x)
284 {
285 init_buffers();
286 typedef typename Protocol::resolver resolver_type;
287 resolver_type resolver(socket().get_executor());
288 connect_to_endpoints(resolver.resolve(x..., ec_));
289 return !ec_ ? this : 0;
290 }
291 #else
292 BOOST_ASIO_VARIADIC_GENERATE(BOOST_ASIO_PRIVATE_CONNECT_DEF)
293 #endif
294
295 /// Close the connection.
296 /**
297 * @return \c this if a connection was successfully established, a null
298 * pointer otherwise.
299 */
300 basic_socket_streambuf* close()
301 {
302 sync();
303 socket().close(ec_);
304 if (!ec_)
305 init_buffers();
306 return !ec_ ? this : 0;
307 }
308
309 /// Get a reference to the underlying socket.
310 basic_socket<Protocol>& socket()
311 {
312 return *this;
313 }
314
315 /// Get the last error associated with the stream buffer.
316 /**
317 * @return An \c error_code corresponding to the last error from the stream
318 * buffer.
319 */
320 const boost::system::error_code& error() const
321 {
322 return ec_;
323 }
324
325 #if !defined(BOOST_ASIO_NO_DEPRECATED)
326 /// (Deprecated: Use error().) Get the last error associated with the stream
327 /// buffer.
328 /**
329 * @return An \c error_code corresponding to the last error from the stream
330 * buffer.
331 */
332 const boost::system::error_code& puberror() const
333 {
334 return error();
335 }
336
337 /// (Deprecated: Use expiry().) Get the stream buffer's expiry time as an
338 /// absolute time.
339 /**
340 * @return An absolute time value representing the stream buffer's expiry
341 * time.
342 */
343 time_point expires_at() const
344 {
345 return expiry_time_;
346 }
347 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
348
349 /// Get the stream buffer's expiry time as an absolute time.
350 /**
351 * @return An absolute time value representing the stream buffer's expiry
352 * time.
353 */
354 time_point expiry() const
355 {
356 return expiry_time_;
357 }
358
359 /// Set the stream buffer's expiry time as an absolute time.
360 /**
361 * This function sets the expiry time associated with the stream. Stream
362 * operations performed after this time (where the operations cannot be
363 * completed using the internal buffers) will fail with the error
364 * boost::asio::error::operation_aborted.
365 *
366 * @param expiry_time The expiry time to be used for the stream.
367 */
368 void expires_at(const time_point& expiry_time)
369 {
370 expiry_time_ = expiry_time;
371 }
372
373 /// Set the stream buffer's expiry time relative to now.
374 /**
375 * This function sets the expiry time associated with the stream. Stream
376 * operations performed after this time (where the operations cannot be
377 * completed using the internal buffers) will fail with the error
378 * boost::asio::error::operation_aborted.
379 *
380 * @param expiry_time The expiry time to be used for the timer.
381 */
382 void expires_after(const duration& expiry_time)
383 {
384 expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
385 }
386
387 #if !defined(BOOST_ASIO_NO_DEPRECATED)
388 /// (Deprecated: Use expiry().) Get the stream buffer's expiry time relative
389 /// to now.
390 /**
391 * @return A relative time value representing the stream buffer's expiry time.
392 */
393 duration expires_from_now() const
394 {
395 return traits_helper::subtract(expires_at(), traits_helper::now());
396 }
397
398 /// (Deprecated: Use expires_after().) Set the stream buffer's expiry time
399 /// relative to now.
400 /**
401 * This function sets the expiry time associated with the stream. Stream
402 * operations performed after this time (where the operations cannot be
403 * completed using the internal buffers) will fail with the error
404 * boost::asio::error::operation_aborted.
405 *
406 * @param expiry_time The expiry time to be used for the timer.
407 */
408 void expires_from_now(const duration& expiry_time)
409 {
410 expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
411 }
412 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
413
414 protected:
415 int_type underflow()
416 {
417 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
418 ec_ = boost::asio::error::operation_not_supported;
419 return traits_type::eof();
420 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
421 if (gptr() != egptr())
422 return traits_type::eof();
423
424 for (;;)
425 {
426 // Check if we are past the expiry time.
427 if (traits_helper::less_than(expiry_time_, traits_helper::now()))
428 {
429 ec_ = boost::asio::error::timed_out;
430 return traits_type::eof();
431 }
432
433 // Try to complete the operation without blocking.
434 if (!socket().native_non_blocking())
435 socket().native_non_blocking(true, ec_);
436 detail::buffer_sequence_adapter<mutable_buffer, mutable_buffer>
437 bufs(boost::asio::buffer(get_buffer_) + putback_max);
438 detail::signed_size_type bytes = detail::socket_ops::recv(
439 socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
440
441 // Check if operation succeeded.
442 if (bytes > 0)
443 {
444 setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
445 &get_buffer_[0] + putback_max + bytes);
446 return traits_type::to_int_type(*gptr());
447 }
448
449 // Check for EOF.
450 if (bytes == 0)
451 {
452 ec_ = boost::asio::error::eof;
453 return traits_type::eof();
454 }
455
456 // Operation failed.
457 if (ec_ != boost::asio::error::would_block
458 && ec_ != boost::asio::error::try_again)
459 return traits_type::eof();
460
461 // Wait for socket to become ready.
462 if (detail::socket_ops::poll_read(
463 socket().native_handle(), 0, timeout(), ec_) < 0)
464 return traits_type::eof();
465 }
466 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
467 }
468
469 int_type overflow(int_type c)
470 {
471 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
472 ec_ = boost::asio::error::operation_not_supported;
473 return traits_type::eof();
474 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
475 char_type ch = traits_type::to_char_type(c);
476
477 // Determine what needs to be sent.
478 const_buffer output_buffer;
479 if (put_buffer_.empty())
480 {
481 if (traits_type::eq_int_type(c, traits_type::eof()))
482 return traits_type::not_eof(c); // Nothing to do.
483 output_buffer = boost::asio::buffer(&ch, sizeof(char_type));
484 }
485 else
486 {
487 output_buffer = boost::asio::buffer(pbase(),
488 (pptr() - pbase()) * sizeof(char_type));
489 }
490
491 while (output_buffer.size() > 0)
492 {
493 // Check if we are past the expiry time.
494 if (traits_helper::less_than(expiry_time_, traits_helper::now()))
495 {
496 ec_ = boost::asio::error::timed_out;
497 return traits_type::eof();
498 }
499
500 // Try to complete the operation without blocking.
501 if (!socket().native_non_blocking())
502 socket().native_non_blocking(true, ec_);
503 detail::buffer_sequence_adapter<
504 const_buffer, const_buffer> bufs(output_buffer);
505 detail::signed_size_type bytes = detail::socket_ops::send(
506 socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
507
508 // Check if operation succeeded.
509 if (bytes > 0)
510 {
511 output_buffer += static_cast<std::size_t>(bytes);
512 continue;
513 }
514
515 // Operation failed.
516 if (ec_ != boost::asio::error::would_block
517 && ec_ != boost::asio::error::try_again)
518 return traits_type::eof();
519
520 // Wait for socket to become ready.
521 if (detail::socket_ops::poll_write(
522 socket().native_handle(), 0, timeout(), ec_) < 0)
523 return traits_type::eof();
524 }
525
526 if (!put_buffer_.empty())
527 {
528 setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
529
530 // If the new character is eof then our work here is done.
531 if (traits_type::eq_int_type(c, traits_type::eof()))
532 return traits_type::not_eof(c);
533
534 // Add the new character to the output buffer.
535 *pptr() = ch;
536 pbump(1);
537 }
538
539 return c;
540 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
541 }
542
543 int sync()
544 {
545 return overflow(traits_type::eof());
546 }
547
548 std::streambuf* setbuf(char_type* s, std::streamsize n)
549 {
550 if (pptr() == pbase() && s == 0 && n == 0)
551 {
552 put_buffer_.clear();
553 setp(0, 0);
554 sync();
555 return this;
556 }
557
558 return 0;
559 }
560
561 private:
562 // Disallow copying and assignment.
563 basic_socket_streambuf(const basic_socket_streambuf&) BOOST_ASIO_DELETED;
564 basic_socket_streambuf& operator=(
565 const basic_socket_streambuf&) BOOST_ASIO_DELETED;
566
567 void init_buffers()
568 {
569 setg(&get_buffer_[0],
570 &get_buffer_[0] + putback_max,
571 &get_buffer_[0] + putback_max);
572
573 if (put_buffer_.empty())
574 setp(0, 0);
575 else
576 setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
577 }
578
579 int timeout() const
580 {
581 int64_t msec = traits_helper::to_posix_duration(
582 traits_helper::subtract(expiry_time_,
583 traits_helper::now())).total_milliseconds();
584 if (msec > (std::numeric_limits<int>::max)())
585 msec = (std::numeric_limits<int>::max)();
586 else if (msec < 0)
587 msec = 0;
588 return static_cast<int>(msec);
589 }
590
591 template <typename EndpointSequence>
592 void connect_to_endpoints(const EndpointSequence& endpoints)
593 {
594 this->connect_to_endpoints(endpoints.begin(), endpoints.end());
595 }
596
597 template <typename EndpointIterator>
598 void connect_to_endpoints(EndpointIterator begin, EndpointIterator end)
599 {
600 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
601 ec_ = boost::asio::error::operation_not_supported;
602 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
603 if (ec_)
604 return;
605
606 ec_ = boost::asio::error::not_found;
607 for (EndpointIterator i = begin; i != end; ++i)
608 {
609 // Check if we are past the expiry time.
610 if (traits_helper::less_than(expiry_time_, traits_helper::now()))
611 {
612 ec_ = boost::asio::error::timed_out;
613 return;
614 }
615
616 // Close and reopen the socket.
617 typename Protocol::endpoint ep(*i);
618 socket().close(ec_);
619 socket().open(ep.protocol(), ec_);
620 if (ec_)
621 continue;
622
623 // Try to complete the operation without blocking.
624 if (!socket().native_non_blocking())
625 socket().native_non_blocking(true, ec_);
626 detail::socket_ops::connect(socket().native_handle(),
627 ep.data(), ep.size(), ec_);
628
629 // Check if operation succeeded.
630 if (!ec_)
631 return;
632
633 // Operation failed.
634 if (ec_ != boost::asio::error::in_progress
635 && ec_ != boost::asio::error::would_block)
636 continue;
637
638 // Wait for socket to become ready.
639 if (detail::socket_ops::poll_connect(
640 socket().native_handle(), timeout(), ec_) < 0)
641 continue;
642
643 // Get the error code from the connect operation.
644 int connect_error = 0;
645 size_t connect_error_len = sizeof(connect_error);
646 if (detail::socket_ops::getsockopt(socket().native_handle(), 0,
647 SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec_)
648 == detail::socket_error_retval)
649 return;
650
651 // Check the result of the connect operation.
652 ec_ = boost::system::error_code(connect_error,
653 boost::asio::error::get_system_category());
654 if (!ec_)
655 return;
656 }
657 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
658 }
659
660 // Helper function to get the maximum expiry time.
661 static time_point max_expiry_time()
662 {
663 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
664 && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
665 return boost::posix_time::pos_infin;
666 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
667 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
668 return (time_point::max)();
669 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
670 // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
671 }
672
673 enum { putback_max = 8 };
674 boost::system::error_code ec_;
675 time_point expiry_time_;
676 };
677
678 } // namespace asio
679 } // namespace boost
680
681 #include <boost/asio/detail/pop_options.hpp>
682
683 #if !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
684 # undef BOOST_ASIO_PRIVATE_CONNECT_DEF
685 #endif // !defined(BOOST_ASIO_HAS_VARIADIC_TEMPLATES)
686
687 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
688
689 #endif // BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP