0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 02:02:38 +01:00

ircd::net::socket: Add non-blocking check() query with interface.

This commit is contained in:
Jason Volk 2019-03-12 14:27:42 -07:00
parent 303233cda4
commit 38f7d61020
4 changed files with 106 additions and 0 deletions

27
include/ircd/net/check.h Normal file
View file

@ -0,0 +1,27 @@
// Matrix Construct
//
// Copyright (C) Matrix Construct Developers, Authors & Contributors
// Copyright (C) 2016-2019 Jason Volk <jason@zemos.net>
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice is present in all copies. The
// full license for this software is available in the LICENSE file.
#pragma once
#define HAVE_IRCD_NET_CHECK_H
namespace ircd::net
{
// !!!
// NOTE: only ready::ERROR is supported for this call at this time.
// !!!
// Check if the socket is ready, similar to wait(), but without blocking.
// Returns true if the socket is ready for that type; false if it is not.
// For ready::ERROR, returning true means the socket has a pending error.
error_code check(std::nothrow_t, socket &, const ready & = ready::ERROR) noexcept;
// Throws any error.
void check(socket &, const ready & = ready::ERROR);
}

View file

@ -43,6 +43,7 @@ namespace ircd::net
#include "open.h"
#include "close.h"
#include "wait.h"
#include "check.h"
#include "read.h"
#include "write.h"
#include "scope_timeout.h"

View file

@ -91,10 +91,15 @@ struct ircd::net::socket
template<class iov> size_t read_few(iov&&); // yielding
template<class iov> size_t read_all(iov&&); // yielding
// low level check suite
error_code check(std::nothrow_t, const ready &) noexcept;
void check(const ready &);
// low level wait suite
void wait(const wait_opts &);
void wait(const wait_opts &, wait_callback_ec);
void wait(const wait_opts &, wait_callback_eptr);
void cancel() noexcept;
// Alias to wait()

View file

@ -415,6 +415,27 @@ ircd::net::read_one(socket &socket,
return socket.read_one(buffers);
}
///////////////////////////////////////////////////////////////////////////////
//
// net/check.h
//
void
ircd::net::check(socket &socket,
const ready &type)
{
socket.check(type);
}
std::error_code
ircd::net::check(std::nothrow_t,
socket &socket,
const ready &type)
noexcept
{
return socket.check(std::nothrow, type);
}
///////////////////////////////////////////////////////////////////////////////
//
// net/wait.h
@ -2326,6 +2347,58 @@ catch(...)
throw;
}
void
ircd::net::socket::check(const ready &type)
{
const error_code ec
{
check(std::nothrow, type)
};
if(ec.value())
throw_system_error(ec);
}
std::error_code
ircd::net::socket::check(std::nothrow_t,
const ready &type)
noexcept
{
assert(type == ready::ERROR);
static char buf[1] alignas(16);
static const ilist<mutable_buffer> bufs{buf};
static const std::error_code eof
{
make_error_code(boost::system::error_code
{
boost::asio::error::eof, boost::asio::error::get_misc_category()
})
};
std::error_code ret;
if(SSL_peek(ssl.native_handle(), buf, sizeof(buf)) >= ssize_t(sizeof(buf)))
return ret;
assert(!blocking(*this));
boost::system::error_code ec;
if(sd.receive(bufs, sd.message_peek, ec) >= ssize_t(sizeof(buf)))
{
assert(!ec.value());
return ret;
}
if(ec.value())
ret = make_error_code(ec);
else
ret = eof;
if(ret == std::errc::resource_unavailable_try_again)
ret = {};
return ret;
}
void
ircd::net::socket::handle_ready(const std::weak_ptr<socket> wp,
const net::ready type,