Skip to content

Feat[MQB]: refactor negotiator #670

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 29 commits into
base: main
Choose a base branch
from

Conversation

emelialei88
Copy link
Collaborator

No description provided.

@emelialei88 emelialei88 changed the title [WIP] Feat/authn: adding protocols for authn Feat[MQB]: adding protocols for authn Apr 4, 2025
@emelialei88 emelialei88 force-pushed the feat/authn branch 4 times, most recently from e6b2fad to 0ee460f Compare April 7, 2025 21:30
@emelialei88 emelialei88 requested a review from Copilot April 7, 2025 21:50
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 28 out of 30 changed files in this pull request and generated no comments.

Files not reviewed (2)
  • src/groups/bmq/bmqp/bmqp_ctrlmsg.xsd: Language not supported
  • src/groups/mqb/mqba/package/mqba.mem: Language not supported
Comments suppressed due to low confidence (2)

src/groups/mqb/mqba/mqba_sessionnegotiator.cpp:1041

  • The 'initiateOutboundNegotiation' function now returns an int. Please verify that all callers consistently handle non-zero error codes and propagate them appropriately.
int rc = initiateOutboundNegotiation(negotiationContext);

src/groups/mqb/mqba/mqba_authenticator.cpp:46

  • [nitpick] The 'readCallback' function is currently empty. Consider providing an implementation or adding tests to validate that read events are handled as expected.
void Authenticator::readCallback(const bmqio::Status&           status,

Copy link
Collaborator

@dorjesinpo dorjesinpo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make the authenticator a separate PR if it is not used?

The prefix initialConnect appears many times, we may want to rethink the names.
The connect part does not match TCP listen context in which it is used.

We have InitialConnectionHandlerContext and InitialConnectionContext
Potentially, they can be even merged (the existing design has them split which is fine). We may need better names.

/// specified `context`.
void negotiate(const bsl::shared_ptr<bmqio::Channel>& channel,
const bsl::shared_ptr<OperationContext>& context);
void initialConnect(const bsl::shared_ptr<bmqio::Channel>& channel,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor. initialConnect seems to apply to both connect and listen results. If so, the name connect in the context of TCP may imply the connect part and the listen part is less obvious.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about "handleInitialConnection"?

scheduleRead(initialConnectionContext);
}
else {
if (d_negotiator_mp->negotiateOutboundOrReverse(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We used to have a comment in SessionNegotiator::negotiate for this case // If this is a 'connect' negotiation, this could either represent an.... Is it gone?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It resides in SessionNegotiator::negotiateOutboundOrReverse now.

scheduleRead(initialConnectionContext);
}
else {
if (d_negotiator_mp->negotiateOutboundOrReverse(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What are the authentication requirements (going to be) in this connect case?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would imagine something similar. We read if it's an incoming request, otherwise maybe have a function like authenticateOutboundOrReverse.

/// needed, the `initialConnectionCb` may be invoked directly from inside
/// the call to `initialConnect()`.
virtual void
initialConnect(mqbnet::InitialConnectionHandlerContext* context,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my other comment about initialConnect name

return; // RETURN
}

switch (context->d_initialConnectionMessage_p.selectionId()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

decodeNegotiationMessage does not have to cache the decoded message (d_initialConnectionMessage_p) if it is used in the same stack frame.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean in the decodeNegotiationMessage we shouldn't create an Event?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that decodeNegotiationMessage does not need to assign to d_negotiationMessage (unless we need to keep the last received message in which case the name should be different). The assignment can happen when we ready to pass the handling to the negotiator

/// `context`, returning 0. Return a non-zero code on error and
/// populate the specified `errorDescription` with a description of the
/// error.
int decodeNegotiationMessage(bsl::ostream& errorDescription,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we add authentication, will this method read authentication messages? If so, do we still want to call that negotiation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed to decodeInitialConnectionMessage

@emelialei88 emelialei88 changed the title Feat[MQB]: adding protocols for authn Feat[MQB]: refactor negotiator Apr 9, 2025
@emelialei88 emelialei88 force-pushed the feat/authn branch 2 times, most recently from a01af08 to c6c893c Compare April 9, 2025 17:17
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot reviewed 24 out of 25 changed files in this pull request and generated no comments.

Files not reviewed (1)
  • src/groups/mqb/mqba/package/mqba.mem: Language not supported
Comments suppressed due to low confidence (1)

src/groups/mqb/mqba/mqba_sessionnegotiator.cpp:296

  • The callback is being passed '*session' (i.e. the object pointed by the shared_ptr) instead of passing the shared_ptr itself. This could lead to undefined behavior if 'session' is empty; please change it to 'session'.
context->d_initialConnectionCb(rc_NO_ADMIN_CALLBACK, error, *session);

@emelialei88 emelialei88 force-pushed the feat/authn branch 5 times, most recently from 623737d to 07e722a Compare April 10, 2025 18:12
Copy link
Collaborator

@dorjesinpo dorjesinpo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A suggestion. Why don't we keep the name NegotiationContext. InitialConnectionHandler creates NegotiationContext when it is ready to pass the connection handling to the negotiator. After all, this is the context for negotiator use.
That way, we clearly separate context for negotiation from the context for pre-negotiation phase (authentication).
And we have one less ``InitialConnection` prefix.

So, the chain looks like this TCPSessionFactory_OperationContext -> InitialConnectionHandlerContext (can be shortened to InitialConnectionContext) -> NegotiationContext

return; // RETURN
}

switch (context->d_initialConnectionMessage_p.selectionId()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that decodeNegotiationMessage does not need to assign to d_negotiationMessage (unless we need to keep the last received message in which case the name should be different). The assignment can happen when we ready to pass the handling to the negotiator

Signed-off-by: Emelia Lei <[email protected]>
Signed-off-by: Emelia Lei <[email protected]>
InitialConnectionContext -> NegotiationContext; InitialConnectionHandlerContext -> InitialConnectionContext

Signed-off-by: Emelia Lei <[email protected]>
@emelialei88 emelialei88 requested a review from dorjesinpo April 11, 2025 16:33
Copy link
Collaborator

@dorjesinpo dorjesinpo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting there. Few more comments

bdlmt::FixedThreadPool d_threadPool;

/// Allocator store to spawn new allocators for sub components.
bmqma::CountingAllocatorStore d_allocators;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it used anywhere?

@@ -475,7 +404,8 @@ SessionNegotiator::onClientIdentityMessage(bsl::ostream& errorDescription,
case bmqp_ctrlmsg::ClientType::E_TCPBROKER:
case bmqp_ctrlmsg::ClientType::E_TCPADMIN: {
if (clientIdentity.hostName().empty()) {
clientIdentity.hostName() = context->d_channelSp->peerUri();
clientIdentity.hostName() =
context->d_initialConnectionContext_p->channel()->peerUri();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feel free to ignore. Could have NegotiationContext::channel() accessor

{
// Create a NegotiationContext for that connection
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BSLS_ASSERT_SAFE(context)


// Disable some compiler warning for simplified write of the
// 'AbstractSessionTestImp'.
#if defined(BSLS_PLATFORM_CMP_CLANG)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as before, no need for the #pragma. Just make handleInitialConnection not inline

if (rc == rc_CONTINUE_READ) {
scheduleRead(context);
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to make sure initialConnectionCompleteCb always gets called. Otherwise, the connection is stuck.

Regarding calling initialConnectionCompleteCb, there may be an option of calling it from InitialConnectionHandler only (never from the Negotiator) if the Negotiator is synchronous. Could make the logic easier to follow.

@dorjesinpo dorjesinpo assigned emelialei88 and unassigned dorjesinpo Apr 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants