32using namespace std::chrono;
33namespace ph = std::placeholders;
43 return (
"bad response");
53 return (
"temporarily unavailable");
55 result << (rc < 0 ?
"error " :
"unknown ") << rc;
56 return (result.str());
70 if (servers.empty()) {
71 isc_throw(BadValue,
"no server");
88 if (servers.empty()) {
89 isc_throw(BadValue,
"no server");
122 :
Exchange(request, maxretries, servers, handler),
127 mutex_(new std::mutex()) {
136 :
Exchange(request, maxretries, servers),
142 mutex_(new std::mutex()) {
160 if (rv.size() !=
sizeof(uint32_t)) {
164 memmove(&ri, &rv[0],
sizeof(uint32_t));
166 rs << hex << setfill(
'0') << setw(8) << ri;
183 .arg(
static_cast<int>(
received_->getIdentifier()))
185 .arg(attr->toString());
249 std::chrono::steady_clock::time_point start_time) {
258 sent_->randomIdentifier();
269 sent_->setSecret(server->getSecret());
275 sent_->setAttributes(attrs);
281 auto delta = steady_clock().now() - start_time;
282 seconds secs = duration_cast<seconds>(delta);
284 static_cast<uint32_t
>(secs.count())));
288 IOAddress local_addr = server->getLocalAddress();
290 if (family == AF_INET) {
294 }
else if (family == AF_INET6) {
305 const vector<uint8_t> zero(AUTH_VECTOR_LEN);
350 if ((
server_->getDeadtime() > 0) &&
355 shared_from_this()));
362 shared_from_this()));
417 .arg(
ep_->getAddress().toText())
418 .arg(
ep_->getPort());
426 }
catch (
const std::exception& exc) {
437 shared_from_this()));
446 unsigned deadtime =
server_->getDeadtime();
459 shared_from_this()));
469 shared_from_this()));
475 shared_from_this()));
522 }
catch (
const std::exception& exc) {
533 shared_from_this()));
540 const boost::system::error_code ec,
553 if (ex->terminated_) {
560 .arg(ex->identifier_)
564 ex->socket_->close();
573 .arg(ex->identifier_)
577 ex->size_ = ex->buffer_.size();
578 ex->socket_->asyncReceive(&(ex->buffer_)[0], ex->size_, 0, ex->ep_.get(),
602 unsigned got =
received_->getIdentifier();
603 unsigned expected =
sent_->getIdentifier();
604 if (got != expected) {
660 }
catch (
const std::exception& exc) {
675 const boost::system::error_code ec,
691 ex->socket_->close();
695 if (ex->terminated_) {
702 .arg(ex->identifier_)
710 (ex->server_->getDeadtime() > 0) &&
711 (ex->server_->getDeadtimeEnd() > ex->start_time_)) {
712 ex->server_->setDeadtimeEnd(ex->start_time_);
717 .arg(ex->identifier_)
719 ex->buffer_.resize(size);
720 ex->received_.reset(
new Message(ex->buffer_, ex->sent_->getAuth(),
721 ex->server_->getSecret()));
723 ex->processResponse();
729 ex->logReplyMessages();
778 handler(shared_from_this());
780 handler(shared_from_this());
805 .arg(ex->identifier_);
809 ex->socket_->cancel();
817 :
Exchange(request, maxretries, servers, handler),
856 .arg(request->size())
857 .arg(
server_->getPeerAddress().toText())
859 .arg(
server_->getTlsContext() ?
" using TLS" :
"");
875 }
catch (
const std::exception& exc) {
885 handler(shared_from_this());
897 const boost::system::error_code& ec,
899 const string& error_msg) {
910 if (exchange->handler_) {
911 auto handler = exchange->handler_;
913 exchange->handler_ =
Handler();
921 .arg(ex->identifier_)
923 if (ec == boost::asio::error::timed_out) {
937 .arg(ex->identifier_)
938 .arg(response->size());
941 ex->received_.reset(
new Message(buffer, ex->sent_->getAuth(),
942 ex->server_->getSecret()));
944 ex->processResponse();
947 ex->logReplyMessages();
949 .arg(ex->identifier_)
953 .arg(ex->identifier_)
962 error_msg =
"null response";
966 if (buffer.size() < AUTH_HDR_LEN) {
969 uint16_t length =
static_cast<uint16_t
>(buffer[2]) << 8;
970 length |=
static_cast<uint16_t
>(buffer[3]);
971 if (length > buffer.size()) {
973 }
else if (length == buffer.size()) {
976 error_msg =
"overflow";
A generic exception that is thrown if a parameter given to a method is considered invalid in that con...
A generic exception that is thrown when an unexpected error condition occurs.
The IOAddress class represents an IP addresses (version agnostic).
short getFamily() const
Returns the address family.
The IOService class is a wrapper for the ASIO io_context class.
The IntervalTimer class is a wrapper for the ASIO boost::asio::system_timer class.
The UDPEndpoint class is a concrete derived class of IOEndpoint that represents an endpoint of a UDP ...
static AttributePtr fromInt(const uint8_t type, const uint32_t value)
From integer with type.
static AttributePtr fromIpAddr(const uint8_t type, const asiolink::IOAddress &value)
From IPv4 address with type.
static AttributePtr fromBinary(const uint8_t type, const std::vector< uint8_t > &value)
From binary with type.
static AttributePtr fromIpv6Addr(const uint8_t type, const asiolink::IOAddress &value)
From IPv6 address with type.
Collection of attributes.
asiolink::UDPSocket< const SocketCallback > RadiusSocket
Type of RADIUS UDP sockets.
Servers servers_
Servers (a copy which is what we need).
Handler handler_
Termination handler.
MessagePtr request_
Request message.
Exchange(const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler)
Constructor.
std::function< void(const ExchangePtr ex)> Handler
Termination handler.
bool sync_
Sync / async flag.
void processResponse()
Process response.
static constexpr size_t BUF_LEN
Receive buffer size.
void createIdentifier()
Create identifier.
MessagePtr received_
Received message.
int rc_
Error/return code.
std::string identifier_
The identifier (random value in hexadecimal).
std::function< void(const boost::system::error_code ec, const size_t size)> SocketCallback
Type of UDP socket callback functions.
MessagePtr sent_
Sent message.
void buildRequest(const ServerPtr &server, std::chrono::steady_clock::time_point start_time)
Build request.
static ExchangePtr create(const asiolink::IOServicePtr io_service, const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler, RadiusProtocol protocol=PW_PROTO_UDP)
Factory.
void logReplyMessages() const
Log reply messages.
unsigned maxretries_
Maximum number of retries for a server.
static std::atomic< bool > shutdown_
Flag which indicates that the instance is shutting down.
isc::tcp::TcpClientPtr tcp_client_
TCP client.
static RadiusImpl & instance()
RadiusImpl is a singleton class.
RADIUS/TCP (or RADIUS/TLS) Exchange.
isc::tcp::WireDataPtr response_
Response wire data.
TcpExchange(const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler)
Constructor.
virtual void shutdown()
Shutdown.
void buildRequest()
Build request.
static int CompleteCheck(const isc::tcp::WireDataPtr &response, std::string &error_msg)
Complete check.
std::chrono::steady_clock::time_point start_time_
Start time.
virtual void start()
Start.
ServerPtr server_
Current server.
static void RequestHandler(TcpExchangePtr ex, const boost::system::error_code &ec, const isc::tcp::WireDataPtr &response, const std::string &error_msg)
Request handler.
asiolink::IOServicePtr io_service_
IO service (argument for async or internal for sync).
boost::scoped_ptr< asiolink::UDPEndpoint > ep_
UDP endpoint.
static void receivedHandler(UdpExchangePtr ex, const boost::system::error_code ec, const size_t size)
Received handler.
void cancelTimer()
Cancel timer.
asiolink::IntervalTimerPtr timer_
Interval timer.
size_t size_
Number of transmitted octests;.
void open()
Instance open.
static void timeoutHandler(UdpExchangePtr ex)
Timeout handler.
virtual ~UdpExchange()
Destructor.
bool started_
Started flag.
virtual void shutdown()
Shutdown.
std::chrono::steady_clock::time_point start_time_
Start time.
void setTimer()
Set timer.
std::list< size_t > postponed_
List of postponed server indexes.
void buildRequest()
Build request.
virtual void shutdownInternal()
Shutdown.
size_t idx_
Current server index.
ServerPtr server_
Current server.
virtual void start()
Start.
std::vector< uint8_t > buffer_
Buffer.
static void openNext(UdpExchangePtr ex)
Class open / open next.
boost::scoped_ptr< RadiusSocket > socket_
Socket.
bool terminated_
Terminated flag.
UdpExchange(const asiolink::IOServicePtr io_service, const MessagePtr &request, unsigned maxretries, const Servers &servers, Handler handler)
Constructor.
unsigned retries_
Retry counter.
void terminate()
Terminate.
static void sentHandler(UdpExchangePtr ex, const boost::system::error_code ec, const size_t size)
Sent handler.
boost::scoped_ptr< std::mutex > mutex_
State change mutex.
static MultiThreadingMgr & instance()
Returns a single instance of Multi Threading Manager.
#define isc_throw(type, stream)
A shortcut macro to insert known values into exception arguments.
#define LOG_ERROR(LOGGER, MESSAGE)
Macro to conveniently test error output and log it.
#define LOG_INFO(LOGGER, MESSAGE)
Macro to conveniently test info output and log it.
#define LOG_DEBUG(LOGGER, LEVEL, MESSAGE)
Macro to conveniently test debug output and log it.
boost::shared_ptr< IOService > IOServicePtr
Defines a smart pointer to an IOService instance.
std::vector< uint8_t > random(size_t len)
Generate random value.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_OPEN_FAILED
@ PW_ACCT_DELAY_TIME
integer.
@ PW_NAS_IPV6_ADDRESS
ipv6addr.
@ PW_NAS_IP_ADDRESS
ipaddr.
@ PW_REPLY_MESSAGE
string.
@ PW_MESSAGE_AUTHENTICATOR
string.
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_MISMATCH
boost::shared_ptr< Attributes > AttributesPtr
Shared pointers to attribute collection.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SYNC_RETURN
boost::shared_ptr< const Attribute > ConstAttributePtr
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_ACCESS_REJECT
const isc::log::MessageID RADIUS_UDP_EXCHANGE_FAILED
boost::shared_ptr< TcpExchange > TcpExchangePtr
Type of shared pointers to RADIUS/TCP exchange object.
string exchangeRCtoText(const int rc)
ExchangeRC value -> name function.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_START
const isc::log::MessageID RADIUS_UDP_EXCHANGE_RECEIVED
const isc::log::MessageID RADIUS_UDP_EXCHANGE_RECEIVE_FAILED
const isc::log::MessageID RADIUS_TCP_EXCHANGE_FAILURE
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_ACCESS_ACCEPT
std::vector< ServerPtr > Servers
Type of RADIUS server collection.
boost::shared_ptr< Exchange > ExchangePtr
Type of shared pointers to RADIUS exchange object.
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SEND_NEW
boost::shared_ptr< Server > ServerPtr
Type of shared pointers to a RADIUS server object.
string msgCodeToText(const uint8_t code)
MsgCode value -> name function.
const int RADIUS_DBG_TRACE
Radius logging levels.
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_ACCOUNTING_RESPONSE
const isc::log::MessageID RADIUS_TCP_EXCHANGE_START_ERROR
const isc::log::MessageID RADIUS_TCP_EXCHANGE_RECEIVED
const isc::log::MessageID RADIUS_TCP_EXCHANGE_SUCCESS
const isc::log::MessageID RADIUS_REPLY_MESSAGE_ATTRIBUTE
const isc::log::MessageID RADIUS_UDP_EXCHANGE_TERMINATE
boost::shared_ptr< UdpExchange > UdpExchangePtr
Type of shared pointers to RADIUS/UDP exchange object.
const isc::log::MessageID RADIUS_TCP_EXCHANGE_SEND
isc::log::Logger radius_logger("radius-hooks")
Radius Logger.
boost::shared_ptr< Message > MessagePtr
Shared pointers to message.
const isc::log::MessageID RADIUS_TCP_EXCHANGE_RECEIVE_FAILED
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_UNEXPECTED
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_BAD_RESPONSE
RadiusProtocol
Transport protocols.
const isc::log::MessageID RADIUS_EXCHANGE_RECEIVED_RESPONSE
const isc::log::MessageID RADIUS_TCP_EXCHANGE_START
const isc::log::MessageID RADIUS_UDP_EXCHANGE_TIMEOUT
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SEND_FAILED
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SENT
const isc::log::MessageID RADIUS_UDP_EXCHANGE_SEND_RETRY
std::vector< uint8_t > WireData
Defines a data structure for storing raw bytes of data on the wire.
boost::shared_ptr< WireData > WireDataPtr
Defines the logger used by the top-level component of kea-lfc.
TCP request/response timeout value.
RAII lock object to protect the code in the same scope with a mutex.