Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:41

0001 //
0002 // basic_socket_streambuf.hpp
0003 // ~~~~~~~~~~~~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
0012 #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 
0020 #if !defined(BOOST_ASIO_NO_IOSTREAM)
0021 
0022 #include <streambuf>
0023 #include <vector>
0024 #include <boost/asio/basic_socket.hpp>
0025 #include <boost/asio/basic_stream_socket.hpp>
0026 #include <boost/asio/detail/buffer_sequence_adapter.hpp>
0027 #include <boost/asio/detail/memory.hpp>
0028 #include <boost/asio/detail/throw_error.hpp>
0029 #include <boost/asio/io_context.hpp>
0030 
0031 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
0032   && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0033 # include <boost/asio/detail/deadline_timer_service.hpp>
0034 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0035       // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0036 # include <boost/asio/steady_timer.hpp>
0037 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0038        // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0039 
0040 #include <boost/asio/detail/push_options.hpp>
0041 
0042 namespace boost {
0043 namespace asio {
0044 namespace detail {
0045 
0046 // A separate base class is used to ensure that the io_context member is
0047 // initialised prior to the basic_socket_streambuf's basic_socket base class.
0048 class socket_streambuf_io_context
0049 {
0050 protected:
0051   socket_streambuf_io_context(io_context* ctx)
0052     : default_io_context_(ctx)
0053   {
0054   }
0055 
0056   shared_ptr<io_context> default_io_context_;
0057 };
0058 
0059 // A separate base class is used to ensure that the dynamically allocated
0060 // buffers are constructed prior to the basic_socket_streambuf's basic_socket
0061 // base class. This makes moving the socket is the last potentially throwing
0062 // step in the streambuf's move constructor, giving the constructor a strong
0063 // exception safety guarantee.
0064 class socket_streambuf_buffers
0065 {
0066 protected:
0067   socket_streambuf_buffers()
0068     : get_buffer_(buffer_size),
0069       put_buffer_(buffer_size)
0070   {
0071   }
0072 
0073   enum { buffer_size = 512 };
0074   std::vector<char> get_buffer_;
0075   std::vector<char> put_buffer_;
0076 };
0077 
0078 } // namespace detail
0079 
0080 #if !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
0081 #define BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL
0082 
0083 // Forward declaration with defaulted arguments.
0084 template <typename Protocol,
0085 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
0086   && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0087     typename Clock = boost::posix_time::ptime,
0088     typename WaitTraits = time_traits<Clock>>
0089 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0090       // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0091     typename Clock = chrono::steady_clock,
0092     typename WaitTraits = wait_traits<Clock>>
0093 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0094        // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0095 class basic_socket_streambuf;
0096 
0097 #endif // !defined(BOOST_ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)
0098 
0099 /// Iostream streambuf for a socket.
0100 #if defined(GENERATING_DOCUMENTATION)
0101 template <typename Protocol,
0102     typename Clock = chrono::steady_clock,
0103     typename WaitTraits = wait_traits<Clock>>
0104 #else // defined(GENERATING_DOCUMENTATION)
0105 template <typename Protocol, typename Clock, typename WaitTraits>
0106 #endif // defined(GENERATING_DOCUMENTATION)
0107 class basic_socket_streambuf
0108   : public std::streambuf,
0109     private detail::socket_streambuf_io_context,
0110     private detail::socket_streambuf_buffers,
0111 #if defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
0112     private basic_socket<Protocol>
0113 #else // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
0114     public basic_socket<Protocol>
0115 #endif // defined(BOOST_ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)
0116 {
0117 private:
0118   // These typedefs are intended keep this class's implementation independent
0119   // of whether it's using Boost.DateClock, Boost.Chrono or std::chrono.
0120 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
0121   && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0122   typedef WaitTraits traits_helper;
0123 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0124       // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0125   typedef detail::chrono_time_traits<Clock, WaitTraits> traits_helper;
0126 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0127        // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0128 
0129 public:
0130   /// The protocol type.
0131   typedef Protocol protocol_type;
0132 
0133   /// The endpoint type.
0134   typedef typename Protocol::endpoint endpoint_type;
0135 
0136   /// The clock type.
0137   typedef Clock clock_type;
0138 
0139 #if defined(GENERATING_DOCUMENTATION)
0140   /// (Deprecated: Use time_point.) The time type.
0141   typedef typename WaitTraits::time_type time_type;
0142 
0143   /// The time type.
0144   typedef typename WaitTraits::time_point time_point;
0145 
0146   /// (Deprecated: Use duration.) The duration type.
0147   typedef typename WaitTraits::duration_type duration_type;
0148 
0149   /// The duration type.
0150   typedef typename WaitTraits::duration duration;
0151 #else
0152 # if !defined(BOOST_ASIO_NO_DEPRECATED)
0153   typedef typename traits_helper::time_type time_type;
0154   typedef typename traits_helper::duration_type duration_type;
0155 # endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0156   typedef typename traits_helper::time_type time_point;
0157   typedef typename traits_helper::duration_type duration;
0158 #endif
0159 
0160   /// Construct a basic_socket_streambuf without establishing a connection.
0161   basic_socket_streambuf()
0162     : detail::socket_streambuf_io_context(new io_context),
0163       basic_socket<Protocol>(*default_io_context_),
0164       expiry_time_(max_expiry_time())
0165   {
0166     init_buffers();
0167   }
0168 
0169   /// Construct a basic_socket_streambuf from the supplied socket.
0170   explicit basic_socket_streambuf(basic_stream_socket<protocol_type> s)
0171     : detail::socket_streambuf_io_context(0),
0172       basic_socket<Protocol>(std::move(s)),
0173       expiry_time_(max_expiry_time())
0174   {
0175     init_buffers();
0176   }
0177 
0178   /// Move-construct a basic_socket_streambuf from another.
0179   basic_socket_streambuf(basic_socket_streambuf&& other)
0180     : detail::socket_streambuf_io_context(other),
0181       basic_socket<Protocol>(std::move(other.socket())),
0182       ec_(other.ec_),
0183       expiry_time_(other.expiry_time_)
0184   {
0185     get_buffer_.swap(other.get_buffer_);
0186     put_buffer_.swap(other.put_buffer_);
0187     setg(other.eback(), other.gptr(), other.egptr());
0188     setp(other.pptr(), other.epptr());
0189     other.ec_ = boost::system::error_code();
0190     other.expiry_time_ = max_expiry_time();
0191     other.init_buffers();
0192   }
0193 
0194   /// Move-assign a basic_socket_streambuf from another.
0195   basic_socket_streambuf& operator=(basic_socket_streambuf&& other)
0196   {
0197     this->close();
0198     socket() = std::move(other.socket());
0199     detail::socket_streambuf_io_context::operator=(other);
0200     ec_ = other.ec_;
0201     expiry_time_ = other.expiry_time_;
0202     get_buffer_.swap(other.get_buffer_);
0203     put_buffer_.swap(other.put_buffer_);
0204     setg(other.eback(), other.gptr(), other.egptr());
0205     setp(other.pptr(), other.epptr());
0206     other.ec_ = boost::system::error_code();
0207     other.expiry_time_ = max_expiry_time();
0208     other.put_buffer_.resize(buffer_size);
0209     other.init_buffers();
0210     return *this;
0211   }
0212 
0213   /// Destructor flushes buffered data.
0214   virtual ~basic_socket_streambuf()
0215   {
0216     if (pptr() != pbase())
0217       overflow(traits_type::eof());
0218   }
0219 
0220   /// Establish a connection.
0221   /**
0222    * This function establishes a connection to the specified endpoint.
0223    *
0224    * @return \c this if a connection was successfully established, a null
0225    * pointer otherwise.
0226    */
0227   basic_socket_streambuf* connect(const endpoint_type& endpoint)
0228   {
0229     init_buffers();
0230     ec_ = boost::system::error_code();
0231     this->connect_to_endpoints(&endpoint, &endpoint + 1);
0232     return !ec_ ? this : 0;
0233   }
0234 
0235   /// Establish a connection.
0236   /**
0237    * This function automatically establishes a connection based on the supplied
0238    * resolver query parameters. The arguments are used to construct a resolver
0239    * query object.
0240    *
0241    * @return \c this if a connection was successfully established, a null
0242    * pointer otherwise.
0243    */
0244   template <typename... T>
0245   basic_socket_streambuf* connect(T... x)
0246   {
0247     init_buffers();
0248     typedef typename Protocol::resolver resolver_type;
0249     resolver_type resolver(socket().get_executor());
0250     connect_to_endpoints(resolver.resolve(x..., ec_));
0251     return !ec_ ? this : 0;
0252   }
0253 
0254   /// Close the connection.
0255   /**
0256    * @return \c this if a connection was successfully established, a null
0257    * pointer otherwise.
0258    */
0259   basic_socket_streambuf* close()
0260   {
0261     sync();
0262     socket().close(ec_);
0263     if (!ec_)
0264       init_buffers();
0265     return !ec_ ? this : 0;
0266   }
0267 
0268   /// Get a reference to the underlying socket.
0269   basic_socket<Protocol>& socket()
0270   {
0271     return *this;
0272   }
0273 
0274   /// Get the last error associated with the stream buffer.
0275   /**
0276    * @return An \c error_code corresponding to the last error from the stream
0277    * buffer.
0278    */
0279   const boost::system::error_code& error() const
0280   {
0281     return ec_;
0282   }
0283 
0284 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0285   /// (Deprecated: Use error().) Get the last error associated with the stream
0286   /// buffer.
0287   /**
0288    * @return An \c error_code corresponding to the last error from the stream
0289    * buffer.
0290    */
0291   const boost::system::error_code& puberror() const
0292   {
0293     return error();
0294   }
0295 
0296   /// (Deprecated: Use expiry().) Get the stream buffer's expiry time as an
0297   /// absolute time.
0298   /**
0299    * @return An absolute time value representing the stream buffer's expiry
0300    * time.
0301    */
0302   time_point expires_at() const
0303   {
0304     return expiry_time_;
0305   }
0306 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0307 
0308   /// Get the stream buffer's expiry time as an absolute time.
0309   /**
0310    * @return An absolute time value representing the stream buffer's expiry
0311    * time.
0312    */
0313   time_point expiry() const
0314   {
0315     return expiry_time_;
0316   }
0317 
0318   /// Set the stream buffer's expiry time as an absolute time.
0319   /**
0320    * This function sets the expiry time associated with the stream. Stream
0321    * operations performed after this time (where the operations cannot be
0322    * completed using the internal buffers) will fail with the error
0323    * boost::asio::error::operation_aborted.
0324    *
0325    * @param expiry_time The expiry time to be used for the stream.
0326    */
0327   void expires_at(const time_point& expiry_time)
0328   {
0329     expiry_time_ = expiry_time;
0330   }
0331 
0332   /// Set the stream buffer's expiry time relative to now.
0333   /**
0334    * This function sets the expiry time associated with the stream. Stream
0335    * operations performed after this time (where the operations cannot be
0336    * completed using the internal buffers) will fail with the error
0337    * boost::asio::error::operation_aborted.
0338    *
0339    * @param expiry_time The expiry time to be used for the timer.
0340    */
0341   void expires_after(const duration& expiry_time)
0342   {
0343     expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
0344   }
0345 
0346 #if !defined(BOOST_ASIO_NO_DEPRECATED)
0347   /// (Deprecated: Use expiry().) Get the stream buffer's expiry time relative
0348   /// to now.
0349   /**
0350    * @return A relative time value representing the stream buffer's expiry time.
0351    */
0352   duration expires_from_now() const
0353   {
0354     return traits_helper::subtract(expires_at(), traits_helper::now());
0355   }
0356 
0357   /// (Deprecated: Use expires_after().) Set the stream buffer's expiry time
0358   /// relative to now.
0359   /**
0360    * This function sets the expiry time associated with the stream. Stream
0361    * operations performed after this time (where the operations cannot be
0362    * completed using the internal buffers) will fail with the error
0363    * boost::asio::error::operation_aborted.
0364    *
0365    * @param expiry_time The expiry time to be used for the timer.
0366    */
0367   void expires_from_now(const duration& expiry_time)
0368   {
0369     expiry_time_ = traits_helper::add(traits_helper::now(), expiry_time);
0370   }
0371 #endif // !defined(BOOST_ASIO_NO_DEPRECATED)
0372 
0373 protected:
0374   int_type underflow()
0375   {
0376 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0377     ec_ = boost::asio::error::operation_not_supported;
0378     return traits_type::eof();
0379 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0380     if (gptr() != egptr())
0381       return traits_type::eof();
0382 
0383     for (;;)
0384     {
0385       // Check if we are past the expiry time.
0386       if (traits_helper::less_than(expiry_time_, traits_helper::now()))
0387       {
0388         ec_ = boost::asio::error::timed_out;
0389         return traits_type::eof();
0390       }
0391 
0392       // Try to complete the operation without blocking.
0393       if (!socket().native_non_blocking())
0394         socket().native_non_blocking(true, ec_);
0395       detail::buffer_sequence_adapter<mutable_buffer, mutable_buffer>
0396         bufs(boost::asio::buffer(get_buffer_) + putback_max);
0397       detail::signed_size_type bytes = detail::socket_ops::recv(
0398           socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
0399 
0400       // Check if operation succeeded.
0401       if (bytes > 0)
0402       {
0403         setg(&get_buffer_[0], &get_buffer_[0] + putback_max,
0404             &get_buffer_[0] + putback_max + bytes);
0405         return traits_type::to_int_type(*gptr());
0406       }
0407 
0408       // Check for EOF.
0409       if (bytes == 0)
0410       {
0411         ec_ = boost::asio::error::eof;
0412         return traits_type::eof();
0413       }
0414 
0415       // Operation failed.
0416       if (ec_ != boost::asio::error::would_block
0417           && ec_ != boost::asio::error::try_again)
0418         return traits_type::eof();
0419 
0420       // Wait for socket to become ready.
0421       if (detail::socket_ops::poll_read(
0422             socket().native_handle(), 0, timeout(), ec_) < 0)
0423         return traits_type::eof();
0424     }
0425 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0426   }
0427 
0428   int_type overflow(int_type c)
0429   {
0430 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0431     ec_ = boost::asio::error::operation_not_supported;
0432     return traits_type::eof();
0433 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0434     char_type ch = traits_type::to_char_type(c);
0435 
0436     // Determine what needs to be sent.
0437     const_buffer output_buffer;
0438     if (put_buffer_.empty())
0439     {
0440       if (traits_type::eq_int_type(c, traits_type::eof()))
0441         return traits_type::not_eof(c); // Nothing to do.
0442       output_buffer = boost::asio::buffer(&ch, sizeof(char_type));
0443     }
0444     else
0445     {
0446       output_buffer = boost::asio::buffer(pbase(),
0447           (pptr() - pbase()) * sizeof(char_type));
0448     }
0449 
0450     while (output_buffer.size() > 0)
0451     {
0452       // Check if we are past the expiry time.
0453       if (traits_helper::less_than(expiry_time_, traits_helper::now()))
0454       {
0455         ec_ = boost::asio::error::timed_out;
0456         return traits_type::eof();
0457       }
0458 
0459       // Try to complete the operation without blocking.
0460       if (!socket().native_non_blocking())
0461         socket().native_non_blocking(true, ec_);
0462       detail::buffer_sequence_adapter<
0463         const_buffer, const_buffer> bufs(output_buffer);
0464       detail::signed_size_type bytes = detail::socket_ops::send(
0465           socket().native_handle(), bufs.buffers(), bufs.count(), 0, ec_);
0466 
0467       // Check if operation succeeded.
0468       if (bytes > 0)
0469       {
0470         output_buffer += static_cast<std::size_t>(bytes);
0471         continue;
0472       }
0473 
0474       // Operation failed.
0475       if (ec_ != boost::asio::error::would_block
0476           && ec_ != boost::asio::error::try_again)
0477         return traits_type::eof();
0478 
0479       // Wait for socket to become ready.
0480       if (detail::socket_ops::poll_write(
0481             socket().native_handle(), 0, timeout(), ec_) < 0)
0482         return traits_type::eof();
0483     }
0484 
0485     if (!put_buffer_.empty())
0486     {
0487       setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
0488 
0489       // If the new character is eof then our work here is done.
0490       if (traits_type::eq_int_type(c, traits_type::eof()))
0491         return traits_type::not_eof(c);
0492 
0493       // Add the new character to the output buffer.
0494       *pptr() = ch;
0495       pbump(1);
0496     }
0497 
0498     return c;
0499 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0500   }
0501 
0502   int sync()
0503   {
0504     return overflow(traits_type::eof());
0505   }
0506 
0507   std::streambuf* setbuf(char_type* s, std::streamsize n)
0508   {
0509     if (pptr() == pbase() && s == 0 && n == 0)
0510     {
0511       put_buffer_.clear();
0512       setp(0, 0);
0513       sync();
0514       return this;
0515     }
0516 
0517     return 0;
0518   }
0519 
0520 private:
0521   // Disallow copying and assignment.
0522   basic_socket_streambuf(const basic_socket_streambuf&) = delete;
0523   basic_socket_streambuf& operator=(
0524       const basic_socket_streambuf&) = delete;
0525 
0526   void init_buffers()
0527   {
0528     setg(&get_buffer_[0],
0529         &get_buffer_[0] + putback_max,
0530         &get_buffer_[0] + putback_max);
0531 
0532     if (put_buffer_.empty())
0533       setp(0, 0);
0534     else
0535       setp(&put_buffer_[0], &put_buffer_[0] + put_buffer_.size());
0536   }
0537 
0538   int timeout() const
0539   {
0540     int64_t msec = traits_helper::to_posix_duration(
0541         traits_helper::subtract(expiry_time_,
0542           traits_helper::now())).total_milliseconds();
0543     if (msec > (std::numeric_limits<int>::max)())
0544       msec = (std::numeric_limits<int>::max)();
0545     else if (msec < 0)
0546       msec = 0;
0547     return static_cast<int>(msec);
0548   }
0549 
0550   template <typename EndpointSequence>
0551   void connect_to_endpoints(const EndpointSequence& endpoints)
0552   {
0553     this->connect_to_endpoints(endpoints.begin(), endpoints.end());
0554   }
0555 
0556   template <typename EndpointIterator>
0557   void connect_to_endpoints(EndpointIterator begin, EndpointIterator end)
0558   {
0559 #if defined(BOOST_ASIO_WINDOWS_RUNTIME)
0560     ec_ = boost::asio::error::operation_not_supported;
0561 #else // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0562     if (ec_)
0563       return;
0564 
0565     ec_ = boost::asio::error::not_found;
0566     for (EndpointIterator i = begin; i != end; ++i)
0567     {
0568       // Check if we are past the expiry time.
0569       if (traits_helper::less_than(expiry_time_, traits_helper::now()))
0570       {
0571         ec_ = boost::asio::error::timed_out;
0572         return;
0573       }
0574 
0575       // Close and reopen the socket.
0576       typename Protocol::endpoint ep(*i);
0577       socket().close(ec_);
0578       socket().open(ep.protocol(), ec_);
0579       if (ec_)
0580         continue;
0581 
0582       // Try to complete the operation without blocking.
0583       if (!socket().native_non_blocking())
0584         socket().native_non_blocking(true, ec_);
0585       detail::socket_ops::connect(socket().native_handle(),
0586           ep.data(), ep.size(), ec_);
0587 
0588       // Check if operation succeeded.
0589       if (!ec_)
0590         return;
0591 
0592       // Operation failed.
0593       if (ec_ != boost::asio::error::in_progress
0594           && ec_ != boost::asio::error::would_block)
0595         continue;
0596 
0597       // Wait for socket to become ready.
0598       if (detail::socket_ops::poll_connect(
0599             socket().native_handle(), timeout(), ec_) < 0)
0600         continue;
0601 
0602       // Get the error code from the connect operation.
0603       int connect_error = 0;
0604       size_t connect_error_len = sizeof(connect_error);
0605       if (detail::socket_ops::getsockopt(socket().native_handle(), 0,
0606             SOL_SOCKET, SO_ERROR, &connect_error, &connect_error_len, ec_)
0607           == detail::socket_error_retval)
0608         return;
0609 
0610       // Check the result of the connect operation.
0611       ec_ = boost::system::error_code(connect_error,
0612           boost::asio::error::get_system_category());
0613       if (!ec_)
0614         return;
0615     }
0616 #endif // defined(BOOST_ASIO_WINDOWS_RUNTIME)
0617   }
0618 
0619   // Helper function to get the maximum expiry time.
0620   static time_point max_expiry_time()
0621   {
0622 #if defined(BOOST_ASIO_HAS_BOOST_DATE_TIME) \
0623   && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0624     return boost::posix_time::pos_infin;
0625 #else // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0626       // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0627     return (time_point::max)();
0628 #endif // defined(BOOST_ASIO_HAS_BOOST_DATE_TIME)
0629        // && defined(BOOST_ASIO_USE_BOOST_DATE_TIME_FOR_SOCKET_IOSTREAM)
0630   }
0631 
0632   enum { putback_max = 8 };
0633   boost::system::error_code ec_;
0634   time_point expiry_time_;
0635 };
0636 
0637 } // namespace asio
0638 } // namespace boost
0639 
0640 #include <boost/asio/detail/pop_options.hpp>
0641 
0642 #endif // !defined(BOOST_ASIO_NO_IOSTREAM)
0643 
0644 #endif // BOOST_ASIO_BASIC_SOCKET_STREAMBUF_HPP