Index: remoting/protocol/negotiating_authenticator.cc |
diff --git a/remoting/protocol/negotiating_authenticator.cc b/remoting/protocol/negotiating_authenticator.cc |
index 7b794d2a05f69a1f8de26ea3dc64b6d80b4773fe..a59241bdd3ff45c21271d11f8d2368eefe1385e5 100644 |
--- a/remoting/protocol/negotiating_authenticator.cc |
+++ b/remoting/protocol/negotiating_authenticator.cc |
@@ -30,20 +30,14 @@ const char kSupportedMethodsSeparator = ','; |
} // namespace |
// static |
-bool NegotiatingAuthenticator::IsNegotiableMessage( |
- const buzz::XmlElement* message) { |
- return message->HasAttr(kSupportedMethodsAttributeQName); |
-} |
- |
-// static |
scoped_ptr<Authenticator> NegotiatingAuthenticator::CreateForClient( |
const std::string& authentication_tag, |
- const std::string& shared_secret, |
+ const FetchSecretCallback& fetch_secret_callback, |
const std::vector<AuthenticationMethod>& methods) { |
scoped_ptr<NegotiatingAuthenticator> result( |
new NegotiatingAuthenticator(MESSAGE_READY)); |
result->authentication_tag_ = authentication_tag; |
- result->shared_secret_ = shared_secret; |
+ result->fetch_secret_callback_ = fetch_secret_callback; |
DCHECK(!methods.empty()); |
for (std::vector<AuthenticationMethod>::const_iterator it = methods.begin(); |
@@ -75,7 +69,8 @@ NegotiatingAuthenticator::NegotiatingAuthenticator( |
Authenticator::State initial_state) |
: current_method_(AuthenticationMethod::Invalid()), |
state_(initial_state), |
- rejection_reason_(INVALID_CREDENTIALS) { |
+ rejection_reason_(INVALID_CREDENTIALS), |
+ weak_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { |
} |
NegotiatingAuthenticator::~NegotiatingAuthenticator() { |
@@ -145,23 +140,36 @@ void NegotiatingAuthenticator::ProcessMessage( |
// Drop the current message because we've chosen a different |
// method. |
- state_ = MESSAGE_READY; |
- } |
- |
- DCHECK(method.is_valid()); |
- |
- // Replace current authenticator if the method has changed. |
- if (method != current_method_) { |
current_method_ = method; |
- CreateAuthenticator(state_); |
+ state_ = PROCESSING_MESSAGE; |
+ CreateAuthenticator(MESSAGE_READY, base::Bind( |
+ &NegotiatingAuthenticator::UpdateState, |
+ base::Unretained(this), resume_callback)); |
+ } else { |
Sergey Ulanov
2013/03/20 05:49:05
nit: add return above and then you won't need "els
rmsousa
2013/03/20 20:17:16
Done.
|
+ if (method != current_method_) { |
+ current_method_ = method; |
+ state_ = PROCESSING_MESSAGE; |
+ // Copy the message since the authenticator may process it asynchronously. |
+ CreateAuthenticator(WAITING_MESSAGE, base::Bind( |
+ &NegotiatingAuthenticator::ProcessMessageInternal, |
+ base::Unretained(this), base::Owned(new buzz::XmlElement(*message)), |
+ resume_callback)); |
+ } else { |
+ ProcessMessageInternal(message, resume_callback); |
+ } |
} |
- if (state_ == WAITING_MESSAGE) { |
+} |
+ |
+void NegotiatingAuthenticator::ProcessMessageInternal( |
Sergey Ulanov
2013/03/20 05:49:05
Move this below so order of functions here matches
rmsousa
2013/03/20 20:17:16
Done.
|
+ const buzz::XmlElement* message, |
+ const base::Closure& resume_callback) { |
+ if (current_authenticator_->state() == WAITING_MESSAGE) { |
+ // If the message was not discarded and the authenticator is waiting for it, |
+ // give it to the underlying authenticator to process. |
// |current_authenticator_| is owned, so Unretained() is safe here. |
current_authenticator_->ProcessMessage(message, base::Bind( |
&NegotiatingAuthenticator::UpdateState, |
base::Unretained(this), resume_callback)); |
- } else { |
- UpdateState(resume_callback); |
} |
} |
@@ -179,27 +187,12 @@ void NegotiatingAuthenticator::UpdateState( |
scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() { |
DCHECK_EQ(state(), MESSAGE_READY); |
- bool add_supported_methods_attr = false; |
+ scoped_ptr<buzz::XmlElement> result; |
- // Initialize current method in case it is not initialized |
- // yet. Normally happens only on client. |
+ // No method yet, just send a message with the list of supported methods. |
+ // Normally happens only on client. |
if (!current_method_.is_valid()) { |
- CHECK(!methods_.empty()); |
- |
- // Initially try the first method. |
- current_method_ = methods_[0]; |
- CreateAuthenticator(MESSAGE_READY); |
- add_supported_methods_attr = true; |
- } |
- |
- scoped_ptr<buzz::XmlElement> result = |
- current_authenticator_->GetNextMessage(); |
- state_ = current_authenticator_->state(); |
- DCHECK_NE(state_, REJECTED); |
- |
- result->AddAttr(kMethodAttributeQName, current_method_.ToString()); |
- |
- if (add_supported_methods_attr) { |
+ result = CreateEmptyAuthenticatorMessage(); |
std::stringstream supported_methods(std::stringstream::out); |
for (std::vector<AuthenticationMethod>::iterator it = methods_.begin(); |
it != methods_.end(); ++it) { |
@@ -208,6 +201,17 @@ scoped_ptr<buzz::XmlElement> NegotiatingAuthenticator::GetNextMessage() { |
supported_methods << it->ToString(); |
} |
result->AddAttr(kSupportedMethodsAttributeQName, supported_methods.str()); |
+ state_ = WAITING_MESSAGE; |
+ } else { |
+ if (current_authenticator_->state() == MESSAGE_READY) { |
+ result = current_authenticator_->GetNextMessage(); |
+ } else { |
+ result = CreateEmptyAuthenticatorMessage(); |
+ } |
+ state_ = current_authenticator_->state(); |
+ DCHECK_NE(state_, REJECTED); |
Sergey Ulanov
2013/03/20 05:49:05
here state can be either WAITING_MESSAGE or ACCEPT
rmsousa
2013/03/20 20:17:16
Done.
|
+ DCHECK_NE(state_, MESSAGE_READY); |
+ result->AddAttr(kMethodAttributeQName, current_method_.ToString()); |
} |
return result.Pass(); |
@@ -228,17 +232,32 @@ bool NegotiatingAuthenticator::is_host_side() const { |
return local_key_pair_.get() != NULL; |
} |
-void NegotiatingAuthenticator::CreateAuthenticator(State initial_state) { |
+ |
Sergey Ulanov
2013/03/20 05:49:05
nit: remove empty line
rmsousa
2013/03/20 20:17:16
Done.
|
+void NegotiatingAuthenticator::CreateAuthenticator( |
+ Authenticator::State preferred_initial_state, |
+ const base::Closure& resume_callback) { |
if (is_host_side()) { |
current_authenticator_ = V2Authenticator::CreateForHost( |
- local_cert_, local_key_pair_, shared_secret_hash_, initial_state); |
+ local_cert_, local_key_pair_, shared_secret_hash_, |
+ preferred_initial_state); |
+ resume_callback.Run(); |
Sergey Ulanov
2013/03/20 05:49:05
Do you need to set state_ here to something other
rmsousa
2013/03/20 20:17:16
The callbacks passed in here all call UpdateState
|
} else { |
- current_authenticator_ = V2Authenticator::CreateForClient( |
- AuthenticationMethod::ApplyHashFunction( |
- current_method_.hash_function(), |
- authentication_tag_, shared_secret_), initial_state); |
+ fetch_secret_callback_.Run(base::Bind( |
+ &NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret, |
+ weak_factory_.GetWeakPtr(), preferred_initial_state, resume_callback)); |
} |
} |
+void NegotiatingAuthenticator::CreateV2AuthenticatorWithSecret( |
+ Authenticator::State initial_state, |
+ const base::Closure& resume_callback, |
+ const std::string& shared_secret) { |
+ current_authenticator_ = V2Authenticator::CreateForClient( |
+ AuthenticationMethod::ApplyHashFunction( |
+ current_method_.hash_function(), authentication_tag_, shared_secret), |
+ initial_state); |
+ resume_callback.Run(); |
Sergey Ulanov
2013/03/20 05:49:05
Set state_ to MESSAGE_READY?
rmsousa
2013/03/20 20:17:16
Same applies, there's an UpdateState in the callba
|
+} |
+ |
} // namespace protocol |
} // namespace remoting |