15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/register_support_host_request.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 105e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/base/constants.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "remoting/host/host_config.h" 14116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/signaling/iq_sender.h" 15116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include "remoting/signaling/signal_strategy.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libjingle/source/talk/xmpp/constants.h" 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "third_party/webrtc/libjingle/xmllite/xmlelement.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using buzz::QName; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using buzz::XmlElement; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace remoting { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Strings used in the request message we send to the bot. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRegisterQueryTag[] = "register-support-host"; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPublicKeyTag[] = "public-key"; 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSignatureTag[] = "signature"; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSignatureTimeAttr[] = "time"; 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Strings used to parse responses received from the bot. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kRegisterQueryResultTag[] = "register-support-host-result"; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSupportIdTag[] = "support-id"; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kSupportIdLifetimeTag[] = "support-id-lifetime"; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RegisterSupportHostRequest::RegisterSupportHostRequest( 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalStrategy* signal_strategy, 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scoped_refptr<RsaKeyPair> key_pair, 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& directory_bot_jid, 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const RegisterCallback& callback) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : signal_strategy_(signal_strategy), 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_pair_(key_pair), 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) directory_bot_jid_(directory_bot_jid), 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback) { 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(signal_strategy_); 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) DCHECK(key_pair_.get()); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal_strategy_->AddListener(this); 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iq_sender_.reset(new IqSender(signal_strategy_)); 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RegisterSupportHostRequest::~RegisterSupportHostRequest() { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (signal_strategy_) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal_strategy_->RemoveListener(this); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterSupportHostRequest::OnSignalStrategyStateChange( 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SignalStrategy::State state) { 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == SignalStrategy::CONNECTED) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!callback_.is_null()); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_ = iq_sender_->SendIq( 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) buzz::STR_SET, directory_bot_jid_, 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CreateRegistrationRequest(signal_strategy_->GetLocalJid()).Pass(), 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&RegisterSupportHostRequest::ProcessResponse, 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (state == SignalStrategy::DISCONNECTED) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We will reach here if signaling fails to connect. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CallCallback(false, std::string(), base::TimeDelta()); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RegisterSupportHostRequest::OnSignalStrategyIncomingStanza( 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const buzz::XmlElement* stanza) { 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<XmlElement> RegisterSupportHostRequest::CreateRegistrationRequest( 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& jid) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<XmlElement> query(new XmlElement( 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QName(kChromotingXmlNamespace, kRegisterQueryTag))); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) XmlElement* public_key = new XmlElement( 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QName(kChromotingXmlNamespace, kPublicKeyTag)); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public_key->AddText(key_pair_->GetPublicKey()); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query->AddElement(public_key); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) query->AddElement(CreateSignature(jid).release()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return query.Pass(); 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr<XmlElement> RegisterSupportHostRequest::CreateSignature( 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& jid) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<XmlElement> signature_tag(new XmlElement( 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QName(kChromotingXmlNamespace, kSignatureTag))); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int64 time = static_cast<int64>(base::Time::Now().ToDoubleT()); 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string time_str(base::Int64ToString(time)); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature_tag->AddAttr( 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QName(kChromotingXmlNamespace, kSignatureTimeAttr), time_str); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string message = jid + ' ' + time_str; 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::string signature(key_pair_->SignMessage(message)); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signature_tag->AddText(signature); 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return signature_tag.Pass(); 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool RegisterSupportHostRequest::ParseResponse(const XmlElement* response, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* support_id, 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta* lifetime) { 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string type = response->Attr(buzz::QN_TYPE); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == buzz::STR_ERROR) { 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received error in response to heartbeat: " 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << response->Str(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This method must only be called for error or result stanzas. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type != buzz::STR_RESULT) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "Received unexpect stanza of type \"" << type << "\""; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const XmlElement* result_element = response->FirstNamed(QName( 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kChromotingXmlNamespace, kRegisterQueryResultTag)); 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!result_element) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "<" << kRegisterQueryResultTag 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "> is missing in the host registration response: " 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << response->Str(); 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const XmlElement* support_id_element = 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_element->FirstNamed(QName(kChromotingXmlNamespace, kSupportIdTag)); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!support_id_element) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "<" << kSupportIdTag 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "> is missing in the host registration response: " 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << response->Str(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const XmlElement* lifetime_element = 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result_element->FirstNamed(QName(kChromotingXmlNamespace, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kSupportIdLifetimeTag)); 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!lifetime_element) { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "<" << kSupportIdLifetimeTag 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "> is missing in the host registration response: " 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << response->Str(); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int lifetime_int; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!base::StringToInt(lifetime_element->BodyText().c_str(), &lifetime_int) || 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lifetime_int <= 0) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "<" << kSupportIdLifetimeTag 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << "> is malformed in the host registration response: " 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << response->Str(); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *support_id = support_id_element->BodyText(); 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *lifetime = base::TimeDelta::FromSeconds(lifetime_int); 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterSupportHostRequest::ProcessResponse(IqRequest* request, 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const XmlElement* response) { 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string support_id; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::TimeDelta lifetime; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success = ParseResponse(response, &support_id, &lifetime); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CallCallback(success, support_id, lifetime); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RegisterSupportHostRequest::CallCallback( 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool success, const std::string& support_id, base::TimeDelta lifetime) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cleanup state before calling the callback. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.reset(); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) iq_sender_.reset(); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal_strategy_->RemoveListener(this); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) signal_strategy_ = NULL; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RegisterCallback callback = callback_; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Reset(); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback.Run(success, support_id, lifetime); 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace remoting 187