Skip to content

Commit 739fa7c

Browse files
committed
adding scheduler/timer; change reauthenticate to look similar as authenticate
Signed-off-by: Emelia Lei <[email protected]>
1 parent 57e5b06 commit 739fa7c

File tree

4 files changed

+167
-42
lines changed

4 files changed

+167
-42
lines changed

src/groups/mqb/mqba/mqba_authenticator.cpp

Lines changed: 131 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@
4545
#include <ball_log.h>
4646
#include <bdlf_bind.h>
4747
#include <bdlma_sequentialallocator.h>
48+
#include <bdlmt_eventscheduler.h>
4849
#include <bdlmt_threadpool.h>
4950
#include <bsl_memory.h>
5051
#include <bsl_ostream.h>
52+
#include <bsl_string_view.h>
5153
#include <bsls_nullptr.h>
5254
#include <bsls_timeinterval.h>
5355

@@ -188,7 +190,8 @@ void Authenticator::authenticate(
188190
rc_AUTHENTICATION_STATE_INCORRECT = -1,
189191
rc_AUTHENTICATION_FAILED = -2,
190192
rc_SEND_AUTHENTICATION_RESPONSE_FAILED = -3,
191-
rc_CONTINUE_READ_FAILED = -4
193+
rc_CONTINUE_READ_FAILED = -4,
194+
rc_AUTHENTICATION_TIMEOUT = -5
192195
};
193196

194197
const AuthenticationContextSp& authenticationContext =
@@ -247,6 +250,28 @@ void Authenticator::authenticate(
247250
bsl::shared_ptr<mqbnet::Session>());
248251
return; // RETURN
249252
}
253+
254+
// Schedule authentication timeout
255+
if (result->lifetimeMs().has_value()) {
256+
bslmt::LockGuard<bslmt::Mutex> guard(
257+
&authenticationContext->timeoutHandleMutex()); // MUTEX LOCKED
258+
259+
if (authenticationContext->timeoutHandle()) {
260+
BALL_LOG_INFO << "timeout handle already has value";
261+
}
262+
263+
d_scheduler.scheduleEvent(
264+
&authenticationContext->timeoutHandle(),
265+
bsls::TimeInterval(bmqsys::Time::nowMonotonicClock())
266+
.addMilliseconds(result->lifetimeMs().value()),
267+
bdlf::BindUtil::bind(
268+
&Authenticator::reauthenticateErrorOrTimeout,
269+
this, // authenticator
270+
rc_AUTHENTICATION_TIMEOUT, // errorCode
271+
"authenticationTimeout", // errorName
272+
channel // channel
273+
));
274+
}
250275
}
251276

252277
// This is when we authenticate with default credentials
@@ -328,7 +353,16 @@ void Authenticator::reauthenticate(
328353
{
329354
// PRECONDITIONS
330355
BSLS_ASSERT(context);
331-
BSLS_ASSERT(context->initialConnectionContext());
356+
357+
enum RcEnum {
358+
// Value for the various RC error categories
359+
rc_SUCCESS = 0,
360+
rc_AUTHENTICATION_STATE_INCORRECT = -1,
361+
rc_AUTHENTICATION_FAILED = -2,
362+
rc_SEND_AUTHENTICATION_RESPONSE_FAILED = -3,
363+
rc_CONTINUE_READ_FAILED = -4,
364+
rc_AUTHENTICATION_TIMEOUT = -5
365+
};
332366

333367
const bmqp_ctrlmsg::AuthenticateRequest& authenticateRequest =
334368
context->authenticationMessage().authenticateRequest();
@@ -352,6 +386,7 @@ void Authenticator::reauthenticate(
352386
&result,
353387
authenticateRequest.mechanism(),
354388
authenticationData);
389+
355390
if (rc != 0) {
356391
BALL_LOG_ERROR << "Reauthentication failed for connection '"
357392
<< channel->peerUri() << "' with mechanism '"
@@ -362,20 +397,6 @@ void Authenticator::reauthenticate(
362397
response.status().code() = rc;
363398
response.status().category() = bmqp_ctrlmsg::StatusCategory::E_REFUSED;
364399
response.status().message() = authenticationErrorStream.str();
365-
366-
// send the error response back to the client before calling the
367-
// completion callback
368-
bmqu::MemOutStream sendResponseErrorStream;
369-
sendAuthenticationMessage(sendResponseErrorStream,
370-
authenticationResponse,
371-
channel,
372-
context->authenticationEncodingType());
373-
374-
bmqio::Status status(bmqio::StatusCategory::e_GENERIC_ERROR,
375-
"reauthenticationError",
376-
rc,
377-
d_allocator_p);
378-
channel->close(status);
379400
}
380401
else {
381402
response.status().code() = 0;
@@ -390,29 +411,73 @@ void Authenticator::reauthenticate(
390411
BALL_LOG_ERROR << "Failed to set (re)authentication state for '"
391412
<< channel->peerUri()
392413
<< "' to 'e_AUTHENTICATED' from 'e_AUTHENTICATING'";
393-
bmqio::Status status(bmqio::StatusCategory::e_GENERIC_ERROR,
394-
"reauthenticationError",
395-
rc,
396-
d_allocator_p);
397-
channel->close(status);
414+
reauthenticateErrorOrTimeout((rc * 10) +
415+
rc_AUTHENTICATION_STATE_INCORRECT,
416+
"reauthenticationError",
417+
channel);
398418
return; // RETURN
399419
}
400420

401-
// send the success response back to the client
402-
bmqu::MemOutStream sendResponseErrorStream;
403-
rc = sendAuthenticationMessage(sendResponseErrorStream,
404-
authenticationResponse,
405-
channel,
406-
context->authenticationEncodingType());
407-
408-
if (rc != 0) {
409-
bmqio::Status status(bmqio::StatusCategory::e_GENERIC_ERROR,
410-
"reauthenticationError",
411-
rc,
412-
d_allocator_p);
413-
channel->close(status);
421+
// Schedule authentication timeout
422+
if (result->lifetimeMs().has_value()) {
423+
bslmt::LockGuard<bslmt::Mutex> guard(
424+
&context->timeoutHandleMutex()); // MUTEX LOCKED
425+
426+
if (context->timeoutHandle()) {
427+
d_scheduler.cancelEvent(&context->timeoutHandle());
428+
}
429+
430+
d_scheduler.scheduleEvent(
431+
&context->timeoutHandle(),
432+
bsls::TimeInterval(bmqsys::Time::nowMonotonicClock() +
433+
result->lifetimeMs().value()),
434+
bdlf::BindUtil::bind(
435+
&Authenticator::reauthenticateErrorOrTimeout,
436+
this, // authenticator
437+
rc_AUTHENTICATION_TIMEOUT, // errorCode
438+
"authenticationTimeout", // errorName
439+
channel // channel
440+
));
414441
}
415442
}
443+
444+
// Send authentication response back to the client
445+
bmqu::MemOutStream sendResponseErrorStream;
446+
rc = sendAuthenticationMessage(sendResponseErrorStream,
447+
authenticationResponse,
448+
channel,
449+
context->authenticationEncodingType());
450+
if (response.status().category() !=
451+
bmqp_ctrlmsg::StatusCategory::E_SUCCESS) {
452+
reauthenticateErrorOrTimeout(rc_AUTHENTICATION_FAILED,
453+
"reauthenticationError",
454+
channel);
455+
}
456+
else if (rc != 0) {
457+
BALL_LOG_ERROR << sendResponseErrorStream.str();
458+
reauthenticateErrorOrTimeout(
459+
(rc * 10) + rc_SEND_AUTHENTICATION_RESPONSE_FAILED,
460+
"reauthenticationError",
461+
channel);
462+
}
463+
464+
return;
465+
}
466+
467+
void Authenticator::reauthenticateErrorOrTimeout(
468+
int errorCode,
469+
bsl::string_view errorName,
470+
const bsl::shared_ptr<bmqio::Channel>& channel)
471+
{
472+
BALL_LOG_ERROR << "Reauthentication error or timeout for '"
473+
<< channel->peerUri() << "' [error: " << errorName
474+
<< ", code: " << errorCode << "]";
475+
476+
bmqio::Status status(bmqio::StatusCategory::e_GENERIC_ERROR,
477+
errorName,
478+
errorCode,
479+
d_allocator_p);
480+
channel->close(status);
416481
}
417482

418483
// CREATORS
@@ -426,6 +491,7 @@ Authenticator::Authenticator(
426491
100, // max threads
427492
bsls::TimeInterval(120).totalMilliseconds(), // idle time
428493
allocator)
494+
, d_scheduler(bsls::SystemClockType::e_MONOTONIC, allocator)
429495
, d_blobSpPool_p(blobSpPool)
430496
, d_allocator_p(allocator)
431497
{
@@ -447,11 +513,19 @@ int Authenticator::start(bsl::ostream& errorDescription)
447513
return rc; // RETURN
448514
}
449515

516+
rc = d_scheduler.start();
517+
if (rc != 0) {
518+
errorDescription << "Failed to start event scheduler for Authenticator"
519+
<< "[rc: " << rc << "]";
520+
return rc; // RETURN
521+
}
522+
450523
return 0;
451524
}
452525

453526
void Authenticator::stop()
454527
{
528+
d_scheduler.stop();
455529
d_threadPool.stop();
456530
}
457531

@@ -462,30 +536,46 @@ int Authenticator::handleAuthentication(
462536
{
463537
enum RcEnum {
464538
// Value for the various RC error categories
465-
rc_SUCCESS = 0,
466-
rc_ERROR = -1,
539+
rc_SUCCESS = 0,
540+
rc_DUPLICATE_AUTHENTICATION = -1,
541+
rc_HANDLE_MESSAGE_FAIL = -2,
542+
rc_INVALID_MESSAGE = -3,
467543
};
468544

469-
bmqu::MemOutStream errStream;
470-
int rc = rc_SUCCESS;
545+
int rc = rc_SUCCESS;
546+
547+
if (context->authenticationContext()) {
548+
errorDescription
549+
<< "Received another authentication message while waiting "
550+
"for negotiation message";
551+
return rc_DUPLICATE_AUTHENTICATION;
552+
}
471553

472554
switch (authenticationMsg.selectionId()) {
473555
case bmqp_ctrlmsg::AuthenticationMessage::
474556
SELECTION_ID_AUTHENTICATE_REQUEST: {
475-
rc = onAuthenticationRequest(errStream, authenticationMsg, context);
557+
rc = onAuthenticationRequest(errorDescription,
558+
authenticationMsg,
559+
context);
476560
} break; // BREAK
477561
case bmqp_ctrlmsg::AuthenticationMessage::
478562
SELECTION_ID_AUTHENTICATE_RESPONSE: {
479-
rc = onAuthenticationResponse(errStream, authenticationMsg, context);
563+
rc = onAuthenticationResponse(errorDescription,
564+
authenticationMsg,
565+
context);
480566
} break; // BREAK
481567
default: {
482568
errorDescription
483569
<< "Invalid authentication message received (unknown type): "
484570
<< authenticationMsg;
485-
return rc_ERROR; // RETURN
571+
return rc_INVALID_MESSAGE; // RETURN
486572
}
487573
}
488574

575+
if (rc != rc_SUCCESS) {
576+
rc = (rc * 10) + rc_HANDLE_MESSAGE_FAIL;
577+
}
578+
489579
return rc;
490580
}
491581

src/groups/mqb/mqba/mqba_authenticator.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,12 @@
4646
// BDE
4747
#include <bdlbb_blob.h>
4848
#include <bdlcc_sharedobjectpool.h>
49+
#include <bdlmt_eventscheduler.h>
4950
#include <bdlmt_threadpool.h>
51+
#include <bdlmt_timereventscheduler.h>
5052
#include <bsl_memory.h>
5153
#include <bsl_ostream.h>
54+
#include <bsl_string_view.h>
5255
#include <bslma_allocator.h>
5356
#include <bslma_usesbslmaallocator.h>
5457
#include <bslmf_nestedtraitdeclaration.h>
@@ -98,6 +101,12 @@ class Authenticator : public mqbnet::Authenticator {
98101

99102
bdlmt::ThreadPool d_threadPool;
100103

104+
/// Used to track the duration of a valid authenticated connection.
105+
/// If reauthentication does not occur within the specified time,
106+
/// an event is triggered to close the channel.
107+
// bdlmt::TimerEventScheduler d_scheduler;
108+
bdlmt::EventScheduler d_scheduler;
109+
101110
BlobSpPool* d_blobSpPool_p;
102111

103112
/// Allocator to use.
@@ -178,6 +187,11 @@ class Authenticator : public mqbnet::Authenticator {
178187
void reauthenticate(const AuthenticationContextSp& context,
179188
const bsl::shared_ptr<bmqio::Channel>& channel);
180189

190+
void reauthenticateErrorOrTimeout(
191+
int errorCode,
192+
bsl::string_view errorName,
193+
const bsl::shared_ptr<bmqio::Channel>& channel);
194+
181195
public:
182196
// TRAITS
183197
BSLMF_NESTED_TRAIT_DECLARATION(Authenticator, bslma::UsesBslmaAllocator)

src/groups/mqb/mqbnet/mqbnet_authenticationcontext.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,10 @@ AuthenticationContext::AuthenticationContext(
4040
State state,
4141
ConnectionType::Enum connectionType,
4242
BSLA_UNUSED bslma::Allocator* allocator)
43-
: d_initialConnectionContext_p(initialConnectionContext)
43+
: d_authenticationResultSp()
44+
, d_initialConnectionContext_p(initialConnectionContext)
4445
, d_authenticationMessage(authenticationMessage)
46+
, d_timeoutHandle()
4547
, d_authenticationEncodingType(authenticationEncodingType)
4648
, d_reauthenticateCb(reauthenticateCb)
4749
, d_state(state)
@@ -136,5 +138,15 @@ ConnectionType::Enum AuthenticationContext::connectionType() const
136138
return d_connectionType;
137139
}
138140

141+
AuthenticationContext::EventHandle& AuthenticationContext::timeoutHandle()
142+
{
143+
return d_timeoutHandle;
144+
}
145+
146+
bslmt::Mutex& AuthenticationContext::timeoutHandleMutex()
147+
{
148+
return d_timeoutHandleMutex;
149+
}
150+
139151
} // namespace mqbnet
140152
} // namespace BloombergLP

src/groups/mqb/mqbnet/mqbnet_authenticationcontext.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <bmqp_protocol.h>
3131

3232
// BDE
33+
#include <bdlmt_eventscheduler.h>
3334
#include <bslma_allocator.h>
3435
#include <bslmt_mutex.h>
3536
#include <bsls_atomic.h>
@@ -50,6 +51,8 @@ class AuthenticationContext {
5051
e_AUTHENTICATED,
5152
};
5253

54+
typedef bdlmt::EventScheduler::EventHandle EventHandle;
55+
5356
typedef bsl::function<int(
5457
bsl::ostream& errorDescription,
5558
const bsl::shared_ptr<AuthenticationContext>& context,
@@ -71,6 +74,9 @@ class AuthenticationContext {
7174

7275
bmqp_ctrlmsg::AuthenticationMessage d_authenticationMessage;
7376

77+
EventHandle d_timeoutHandle;
78+
bslmt::Mutex d_timeoutHandleMutex;
79+
7480
/// The encoding type used for sending a message. It should match with the
7581
/// encoding type of the received message.
7682
bmqp::EncodingType::Enum d_authenticationEncodingType;
@@ -127,6 +133,9 @@ class AuthenticationContext {
127133
bmqp::EncodingType::Enum authenticationEncodingType() const;
128134
const ReauthenticateCb& reauthenticateCb() const;
129135
ConnectionType::Enum connectionType() const;
136+
137+
EventHandle& timeoutHandle();
138+
bslmt::Mutex& timeoutHandleMutex();
130139
};
131140

132141
} // close package namespace

0 commit comments

Comments
 (0)