317 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			317 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
	
| //
 | |
| // detail/socket_option.hpp
 | |
| // ~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| //
 | |
| // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
 | |
| //
 | |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying
 | |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
 | |
| //
 | |
| 
 | |
| #ifndef ASIO_DETAIL_SOCKET_OPTION_HPP
 | |
| #define ASIO_DETAIL_SOCKET_OPTION_HPP
 | |
| 
 | |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200)
 | |
| # pragma once
 | |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
 | |
| 
 | |
| #include "asio/detail/config.hpp"
 | |
| #include <cstddef>
 | |
| #include <stdexcept>
 | |
| #include "asio/detail/socket_types.hpp"
 | |
| #include "asio/detail/throw_exception.hpp"
 | |
| 
 | |
| #include "asio/detail/push_options.hpp"
 | |
| 
 | |
| namespace asio {
 | |
| namespace detail {
 | |
| namespace socket_option {
 | |
| 
 | |
| // Helper template for implementing boolean-based options.
 | |
| template <int Level, int Name>
 | |
| class boolean
 | |
| {
 | |
| public:
 | |
|   // Default constructor.
 | |
|   boolean()
 | |
|     : value_(0)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   // Construct with a specific option value.
 | |
|   explicit boolean(bool v)
 | |
|     : value_(v ? 1 : 0)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   // Set the current value of the boolean.
 | |
|   boolean& operator=(bool v)
 | |
|   {
 | |
|     value_ = v ? 1 : 0;
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   // Get the current value of the boolean.
 | |
|   bool value() const
 | |
|   {
 | |
|     return !!value_;
 | |
|   }
 | |
| 
 | |
|   // Convert to bool.
 | |
|   operator bool() const
 | |
|   {
 | |
|     return !!value_;
 | |
|   }
 | |
| 
 | |
|   // Test for false.
 | |
|   bool operator!() const
 | |
|   {
 | |
|     return !value_;
 | |
|   }
 | |
| 
 | |
|   // Get the level of the socket option.
 | |
|   template <typename Protocol>
 | |
|   int level(const Protocol&) const
 | |
|   {
 | |
|     return Level;
 | |
|   }
 | |
| 
 | |
|   // Get the name of the socket option.
 | |
|   template <typename Protocol>
 | |
|   int name(const Protocol&) const
 | |
|   {
 | |
|     return Name;
 | |
|   }
 | |
| 
 | |
|   // Get the address of the boolean data.
 | |
|   template <typename Protocol>
 | |
|   int* data(const Protocol&)
 | |
|   {
 | |
|     return &value_;
 | |
|   }
 | |
| 
 | |
|   // Get the address of the boolean data.
 | |
|   template <typename Protocol>
 | |
|   const int* data(const Protocol&) const
 | |
|   {
 | |
|     return &value_;
 | |
|   }
 | |
| 
 | |
|   // Get the size of the boolean data.
 | |
|   template <typename Protocol>
 | |
|   std::size_t size(const Protocol&) const
 | |
|   {
 | |
|     return sizeof(value_);
 | |
|   }
 | |
| 
 | |
|   // Set the size of the boolean data.
 | |
|   template <typename Protocol>
 | |
|   void resize(const Protocol&, std::size_t s)
 | |
|   {
 | |
|     // On some platforms (e.g. Windows Vista), the getsockopt function will
 | |
|     // return the size of a boolean socket option as one byte, even though a
 | |
|     // four byte integer was passed in.
 | |
|     switch (s)
 | |
|     {
 | |
|     case sizeof(char):
 | |
|       value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0;
 | |
|       break;
 | |
|     case sizeof(value_):
 | |
|       break;
 | |
|     default:
 | |
|       {
 | |
|         std::length_error ex("boolean socket option resize");
 | |
|         asio::detail::throw_exception(ex);
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   int value_;
 | |
| };
 | |
| 
 | |
| // Helper template for implementing integer options.
 | |
| template <int Level, int Name>
 | |
| class integer
 | |
| {
 | |
| public:
 | |
|   // Default constructor.
 | |
|   integer()
 | |
|     : value_(0)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   // Construct with a specific option value.
 | |
|   explicit integer(int v)
 | |
|     : value_(v)
 | |
|   {
 | |
|   }
 | |
| 
 | |
|   // Set the value of the int option.
 | |
|   integer& operator=(int v)
 | |
|   {
 | |
|     value_ = v;
 | |
|     return *this;
 | |
|   }
 | |
| 
 | |
|   // Get the current value of the int option.
 | |
|   int value() const
 | |
|   {
 | |
|     return value_;
 | |
|   }
 | |
| 
 | |
|   // Get the level of the socket option.
 | |
|   template <typename Protocol>
 | |
|   int level(const Protocol&) const
 | |
|   {
 | |
|     return Level;
 | |
|   }
 | |
| 
 | |
|   // Get the name of the socket option.
 | |
|   template <typename Protocol>
 | |
|   int name(const Protocol&) const
 | |
|   {
 | |
|     return Name;
 | |
|   }
 | |
| 
 | |
|   // Get the address of the int data.
 | |
|   template <typename Protocol>
 | |
|   int* data(const Protocol&)
 | |
|   {
 | |
|     return &value_;
 | |
|   }
 | |
| 
 | |
|   // Get the address of the int data.
 | |
|   template <typename Protocol>
 | |
|   const int* data(const Protocol&) const
 | |
|   {
 | |
|     return &value_;
 | |
|   }
 | |
| 
 | |
|   // Get the size of the int data.
 | |
|   template <typename Protocol>
 | |
|   std::size_t size(const Protocol&) const
 | |
|   {
 | |
|     return sizeof(value_);
 | |
|   }
 | |
| 
 | |
|   // Set the size of the int data.
 | |
|   template <typename Protocol>
 | |
|   void resize(const Protocol&, std::size_t s)
 | |
|   {
 | |
|     if (s != sizeof(value_))
 | |
|     {
 | |
|       std::length_error ex("integer socket option resize");
 | |
|       asio::detail::throw_exception(ex);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   int value_;
 | |
| };
 | |
| 
 | |
| // Helper template for implementing linger options.
 | |
| template <int Level, int Name>
 | |
| class linger
 | |
| {
 | |
| public:
 | |
|   // Default constructor.
 | |
|   linger()
 | |
|   {
 | |
|     value_.l_onoff = 0;
 | |
|     value_.l_linger = 0;
 | |
|   }
 | |
| 
 | |
|   // Construct with specific option values.
 | |
|   linger(bool e, int t)
 | |
|   {
 | |
|     enabled(e);
 | |
|     timeout ASIO_PREVENT_MACRO_SUBSTITUTION(t);
 | |
|   }
 | |
| 
 | |
|   // Set the value for whether linger is enabled.
 | |
|   void enabled(bool value)
 | |
|   {
 | |
|     value_.l_onoff = value ? 1 : 0;
 | |
|   }
 | |
| 
 | |
|   // Get the value for whether linger is enabled.
 | |
|   bool enabled() const
 | |
|   {
 | |
|     return value_.l_onoff != 0;
 | |
|   }
 | |
| 
 | |
|   // Set the value for the linger timeout.
 | |
|   void timeout ASIO_PREVENT_MACRO_SUBSTITUTION(int value)
 | |
|   {
 | |
| #if defined(WIN32)
 | |
|     value_.l_linger = static_cast<u_short>(value);
 | |
| #else
 | |
|     value_.l_linger = value;
 | |
| #endif
 | |
|   }
 | |
| 
 | |
|   // Get the value for the linger timeout.
 | |
|   int timeout ASIO_PREVENT_MACRO_SUBSTITUTION() const
 | |
|   {
 | |
|     return static_cast<int>(value_.l_linger);
 | |
|   }
 | |
| 
 | |
|   // Get the level of the socket option.
 | |
|   template <typename Protocol>
 | |
|   int level(const Protocol&) const
 | |
|   {
 | |
|     return Level;
 | |
|   }
 | |
| 
 | |
|   // Get the name of the socket option.
 | |
|   template <typename Protocol>
 | |
|   int name(const Protocol&) const
 | |
|   {
 | |
|     return Name;
 | |
|   }
 | |
| 
 | |
|   // Get the address of the linger data.
 | |
|   template <typename Protocol>
 | |
|   detail::linger_type* data(const Protocol&)
 | |
|   {
 | |
|     return &value_;
 | |
|   }
 | |
| 
 | |
|   // Get the address of the linger data.
 | |
|   template <typename Protocol>
 | |
|   const detail::linger_type* data(const Protocol&) const
 | |
|   {
 | |
|     return &value_;
 | |
|   }
 | |
| 
 | |
|   // Get the size of the linger data.
 | |
|   template <typename Protocol>
 | |
|   std::size_t size(const Protocol&) const
 | |
|   {
 | |
|     return sizeof(value_);
 | |
|   }
 | |
| 
 | |
|   // Set the size of the int data.
 | |
|   template <typename Protocol>
 | |
|   void resize(const Protocol&, std::size_t s)
 | |
|   {
 | |
|     if (s != sizeof(value_))
 | |
|     {
 | |
|       std::length_error ex("linger socket option resize");
 | |
|       asio::detail::throw_exception(ex);
 | |
|     }
 | |
|   }
 | |
| 
 | |
| private:
 | |
|   detail::linger_type value_;
 | |
| };
 | |
| 
 | |
| } // namespace socket_option
 | |
| } // namespace detail
 | |
| } // namespace asio
 | |
| 
 | |
| #include "asio/detail/pop_options.hpp"
 | |
| 
 | |
| #endif // ASIO_DETAIL_SOCKET_OPTION_HPP
 |