10 #if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT 14 #if defined __OpenBSD__ 15 # include <sys/types.h> 16 # include <sys/sysctl.h> 17 # include <netinet/tcp_timer.h> 18 # include <netinet/tcp_var.h> 43 if( _read_in_progress.valid() )
46 _read_in_progress.wait();
51 if( _write_in_progress.valid() )
54 _write_in_progress.wait();
60 virtual size_t readsome(boost::asio::ip::tcp::socket& socket,
char* buffer,
size_t length)
override;
61 virtual size_t readsome(boost::asio::ip::tcp::socket& socket,
const std::shared_ptr<char>& buffer,
size_t length,
size_t offset)
override;
62 virtual size_t writesome(boost::asio::ip::tcp::socket& socket,
const char* buffer,
size_t length)
override;
63 virtual size_t writesome(boost::asio::ip::tcp::socket& socket,
const std::shared_ptr<const char>& buffer,
size_t length,
size_t offset)
override;
67 boost::asio::ip::tcp::socket
_sock;
75 size_t tcp_socket::impl::readsome(boost::asio::ip::tcp::socket& socket,
const std::shared_ptr<char>& buffer,
size_t length,
size_t offset)
83 size_t tcp_socket::impl::writesome(boost::asio::ip::tcp::socket& socket,
const std::shared_ptr<const char>& buffer,
size_t length,
size_t offset)
95 return my->_sock.is_open();
113 return !my->_sock.is_open();
118 return my->_io_hooks->writesome(my->_sock, buf, len);
123 return my->_io_hooks->writesome(my->_sock, buf, len, offset);
130 auto rep = my->_sock.remote_endpoint();
141 auto boost_local_endpoint = my->_sock.local_endpoint();
142 return fc::ip::endpoint(boost_local_endpoint.address().to_v4().to_ulong(), boost_local_endpoint.port() );
149 return my->_io_hooks->readsome(my->_sock, buf, len);
153 return my->_io_hooks->readsome(my->_sock, buf, len, offset);
165 local_endpoint.
port()));
167 catch (
const std::exception& except)
169 elog(
"Exception binding outgoing connection to desired local endpoint ${endpoint}: ${what}", (
"endpoint", local_endpoint)(
"what", except.what()));
170 FC_THROW(
"error binding to ${endpoint}: ${what}", (
"endpoint", local_endpoint)(
"what", except.what()));
176 if (interval.
count() > 0)
178 boost::asio::socket_base::keep_alive option(
true);
179 my->_sock.set_option(option);
180 #if defined _WIN32 || defined WIN32 || defined OS_WIN64 || defined _WIN64 || defined WIN64 || defined WINNT 181 struct tcp_keepalive keepalive_settings;
182 keepalive_settings.onoff = 1;
186 DWORD dwBytesRet = 0;
187 if (WSAIoctl(my->_sock.native_handle(), SIO_KEEPALIVE_VALS, &keepalive_settings,
sizeof(keepalive_settings),
188 NULL, 0, &dwBytesRet, NULL, NULL) == SOCKET_ERROR)
189 wlog(
"Error setting TCP keepalive values");
190 #elif !defined(__clang__) || (__clang_major__ >= 6) 193 if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP,
194 #if defined( __APPLE__ ) 196 #elif defined( __OpenBSD__ ) 201 (
char*)&timeout_sec,
sizeof(timeout_sec)) < 0)
202 wlog(
"Error setting TCP keepalive idle time");
203 # if defined(__OpenBSD__) 207 name[2] = IPPROTO_TCP;
213 name[3] = TCPCTL_SLOWHZ;
214 if (sysctl(name, 4, &value, &sz, NULL, 0) == -1)
215 wlog(
"Error setting TCP keepalive interval");
218 value *= timeout_sec;
219 name[3] = TCPCTL_KEEPINTVL;
220 if (sysctl(name, 4, NULL, NULL, &value,
sizeof(value)) == -1)
221 wlog(
"Error setting TCP keepalive interval");
222 # elif !defined(__APPLE__) || defined(TCP_KEEPINTVL) // TCP_KEEPINTVL not defined before 10.9 223 if (setsockopt(my->_sock.native_handle(), IPPROTO_TCP, TCP_KEEPINTVL,
224 (
char*)&timeout_sec,
sizeof(timeout_sec)) < 0)
225 wlog(
"Error setting TCP keepalive interval");
226 # endif // (__OpenBSD__) or (!__APPLE__ || TCP_KEEPINTVL) 231 boost::asio::socket_base::keep_alive option(
false);
232 my->_sock.set_option(option);
238 my->_io_hooks = new_hooks ? new_hooks : &*my;
244 boost::asio::socket_base::reuse_address option(enable);
245 my->_sock.set_option(option);
246 #if defined(__APPLE__) || defined(__linux__) 247 # ifndef SO_REUSEPORT 248 # define SO_REUSEPORT 15 254 int reuseport_value = 1;
255 if (setsockopt(my->_sock.native_handle(), SOL_SOCKET, SO_REUSEPORT,
256 (
char*)&reuseport_value,
sizeof(reuseport_value)) < 0)
258 if (errno == ENOPROTOOPT)
261 wlog(
"Error setting SO_REUSEPORT");
280 catch ( boost::system::system_error& )
289 if( my && my->_accept.is_open() )
314 boost::asio::ip::tcp::acceptor::reuse_address option(enable);
315 my->
_accept.set_option(option);
316 #if defined(__APPLE__) || (defined(__linux__) && defined(SO_REUSEPORT)) 321 int reuseport_value = 1;
322 if (setsockopt(my->
_accept.native_handle(), SOL_SOCKET, SO_REUSEPORT,
323 (
char*)&reuseport_value,
sizeof(reuseport_value)) < 0)
325 if (errno == ENOPROTOOPT)
328 wlog(
"Error setting SO_REUSEPORT");
360 my->
_accept.local_endpoint().port() );
366 return my->
_accept.local_endpoint().port();
uint16_t get_port() const
future< size_t > write_some(AsyncWriteStream &s, const ConstBufferSequence &buf)
wraps boost::asio::async_write_some
void set_io_hooks(tcp_socket_io_hooks *new_hooks)
virtual size_t writesome(boost::asio::ip::tcp::socket &socket, const char *buffer, size_t length) override
boost::asio::ip::tcp::acceptor _accept
microseconds milliseconds(int64_t s)
void bind(const fc::ip::endpoint &local_endpoint)
boost::asio::ip::tcp::socket _sock
void enable_keep_alives(const fc::microseconds &interval)
void connect(AsyncSocket &sock, const EndpointType &ep)
wraps boost::asio::socket::async_connect
#define FC_RETHROW_EXCEPTIONS(LOG_LEVEL, FORMAT,...)
Catchs all exception's, std::exceptions, and ... and rethrows them after appending the provided log m...
fc::future< size_t > _write_in_progress
void accept(AcceptorType &acc, SocketType &sock)
wraps boost::asio::async_accept
void set_reuse_address(bool enable=true)
virtual size_t readsome(boost::asio::ip::tcp::socket &socket, char *buffer, size_t length) override
microseconds seconds(int64_t s)
const address & get_address() const
#define FC_ASSERT(TEST,...)
Checks a condition and throws an assert_exception if the test is FALSE.
void connect_to(const fc::ip::endpoint &remote_endpoint)
fc::ip::endpoint get_local_endpoint() const
fc::ip::endpoint remote_endpoint() const
boost::asio::ip::tcp::endpoint endpoint
void listen(uint16_t port)
virtual size_t readsome(char *buffer, size_t max)
Defines exception's used by fc.
future< size_t > read_some(AsyncReadStream &s, const MutableBufferSequence &buf)
boost::asio::io_service & default_io_service()
tcp_socket_io_hooks * _io_hooks
void accept(tcp_socket &s)
fc::future< size_t > _read_in_progress
fc::ip::endpoint local_endpoint() const
void set_reuse_address(bool enable=true)
virtual size_t writesome(const char *buffer, size_t len)