| Index: remoting/protocol/jingle_session.cc
|
| diff --git a/remoting/protocol/jingle_session.cc b/remoting/protocol/jingle_session.cc
|
| index edc48eea6b6649d4de693cab122266516821dc0b..0f4f0a2ea6092236162ff8c7dfbfa5dcc8eb302b 100644
|
| --- a/remoting/protocol/jingle_session.cc
|
| +++ b/remoting/protocol/jingle_session.cc
|
| @@ -32,12 +32,11 @@ namespace remoting {
|
| namespace protocol {
|
|
|
| namespace {
|
| -// Delay after candidate creation before sending transport-info
|
| -// message. This is neccessary to be able to pack multiple candidates
|
| -// into one transport-info messages. The value needs to be greater
|
| -// than zero because ports are opened asynchronously in the browser
|
| -// process.
|
| -const int kTransportInfoSendDelayMs = 2;
|
| +
|
| +// Delay after candidate creation before sending transport-info message to
|
| +// accumulate multiple candidates. This is an optimization to reduce number of
|
| +// transport-info messages.
|
| +const int kTransportInfoSendDelayMs = 20;
|
|
|
| // How long we should wait for a response from the other end. This value is used
|
| // for all requests except |transport-info|.
|
| @@ -74,7 +73,6 @@ JingleSession::JingleSession(JingleSessionManager* session_manager)
|
| event_handler_(nullptr),
|
| state_(INITIALIZING),
|
| error_(OK),
|
| - config_is_set_(false),
|
| weak_factory_(this) {
|
| }
|
|
|
| @@ -149,7 +147,7 @@ void JingleSession::InitializeIncomingConnection(
|
|
|
| void JingleSession::AcceptIncomingConnection(
|
| const JingleMessage& initiate_message) {
|
| - DCHECK(config_is_set_);
|
| + DCHECK(config_);
|
|
|
| // Process the first authentication message.
|
| const buzz::XmlElement* first_auth_message =
|
| @@ -184,7 +182,7 @@ void JingleSession::ContinueAcceptIncomingConnection() {
|
| auth_message = authenticator_->GetNextMessage();
|
|
|
| message.description.reset(
|
| - new ContentDescription(CandidateSessionConfig::CreateFrom(config_),
|
| + new ContentDescription(CandidateSessionConfig::CreateFrom(*config_),
|
| auth_message.Pass()));
|
| SendMessage(message);
|
|
|
| @@ -213,14 +211,13 @@ const CandidateSessionConfig* JingleSession::candidate_config() {
|
|
|
| const SessionConfig& JingleSession::config() {
|
| DCHECK(CalledOnValidThread());
|
| - return config_;
|
| + return *config_;
|
| }
|
|
|
| -void JingleSession::set_config(const SessionConfig& config) {
|
| +void JingleSession::set_config(scoped_ptr<SessionConfig> config) {
|
| DCHECK(CalledOnValidThread());
|
| - DCHECK(!config_is_set_);
|
| - config_ = config;
|
| - config_is_set_ = true;
|
| + DCHECK(!config_);
|
| + config_ = config.Pass();
|
| }
|
|
|
| StreamChannelFactory* JingleSession::GetTransportChannelFactory() {
|
| @@ -243,16 +240,26 @@ void JingleSession::Close() {
|
| CloseInternal(OK);
|
| }
|
|
|
| -void JingleSession::AddPendingRemoteCandidates(Transport* channel,
|
| - const std::string& name) {
|
| - std::list<JingleMessage::NamedCandidate>::iterator it =
|
| +void JingleSession::AddPendingRemoteTransportInfo(Transport* channel) {
|
| + std::list<JingleMessage::IceCredentials>::iterator credentials =
|
| + pending_remote_ice_credentials_.begin();
|
| + while (credentials != pending_remote_ice_credentials_.end()) {
|
| + if (credentials->channel == channel->name()) {
|
| + channel->SetRemoteCredentials(credentials->ufrag, credentials->password);
|
| + credentials = pending_remote_ice_credentials_.erase(credentials);
|
| + } else {
|
| + ++credentials;
|
| + }
|
| + }
|
| +
|
| + std::list<JingleMessage::NamedCandidate>::iterator candidate =
|
| pending_remote_candidates_.begin();
|
| - while(it != pending_remote_candidates_.end()) {
|
| - if (it->name == name) {
|
| - channel->AddRemoteCandidate(it->candidate);
|
| - it = pending_remote_candidates_.erase(it);
|
| + while (candidate != pending_remote_candidates_.end()) {
|
| + if (candidate->name == channel->name()) {
|
| + channel->AddRemoteCandidate(candidate->candidate);
|
| + candidate = pending_remote_candidates_.erase(candidate);
|
| } else {
|
| - ++it;
|
| + ++candidate;
|
| }
|
| }
|
| }
|
| @@ -263,8 +270,9 @@ void JingleSession::CreateChannel(const std::string& name,
|
|
|
| scoped_ptr<Transport> channel =
|
| session_manager_->transport_factory_->CreateTransport();
|
| + channel->SetUseStandardIce(config_->standard_ice());
|
| channel->Connect(name, this, callback);
|
| - AddPendingRemoteCandidates(channel.get(), name);
|
| + AddPendingRemoteTransportInfo(channel.get());
|
| channels_[name] = channel.release();
|
| }
|
|
|
| @@ -277,18 +285,19 @@ void JingleSession::CancelChannelCreation(const std::string& name) {
|
| }
|
| }
|
|
|
| +void JingleSession::OnTransportIceCredentials(Transport* transport,
|
| + const std::string& ufrag,
|
| + const std::string& password) {
|
| + EnsurePendingTransportInfoMessage();
|
| + pending_transport_info_message_->ice_credentials.push_back(
|
| + JingleMessage::IceCredentials(transport->name(), ufrag, password));
|
| +}
|
| +
|
| void JingleSession::OnTransportCandidate(Transport* transport,
|
| const cricket::Candidate& candidate) {
|
| - pending_candidates_.push_back(JingleMessage::NamedCandidate(
|
| - transport->name(), candidate));
|
| -
|
| - if (!transport_infos_timer_.IsRunning()) {
|
| - // Delay sending the new candidates in case we get more candidates
|
| - // that we can send in one message.
|
| - transport_infos_timer_.Start(
|
| - FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
|
| - this, &JingleSession::SendTransportInfo);
|
| - }
|
| + EnsurePendingTransportInfoMessage();
|
| + pending_transport_info_message_->candidates.push_back(
|
| + JingleMessage::NamedCandidate(transport->name(), candidate));
|
| }
|
|
|
| void JingleSession::OnTransportRouteChange(Transport* transport,
|
| @@ -362,14 +371,33 @@ void JingleSession::OnMessageResponse(
|
| }
|
| }
|
|
|
| +void JingleSession::EnsurePendingTransportInfoMessage() {
|
| + // |transport_info_timer_| must be running iff
|
| + // |pending_transport_info_message_| exists.
|
| + DCHECK_EQ(pending_transport_info_message_ != nullptr,
|
| + transport_info_timer_.IsRunning());
|
| +
|
| + if (!pending_transport_info_message_) {
|
| + pending_transport_info_message_.reset(new JingleMessage(
|
| + peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_));
|
| + pending_transport_info_message_->standard_ice = config_->standard_ice();
|
| +
|
| + // Delay sending the new candidates in case we get more candidates
|
| + // that we can send in one message.
|
| + transport_info_timer_.Start(
|
| + FROM_HERE, base::TimeDelta::FromMilliseconds(kTransportInfoSendDelayMs),
|
| + this, &JingleSession::SendTransportInfo);
|
| + }
|
| +}
|
| +
|
| void JingleSession::SendTransportInfo() {
|
| - JingleMessage message(peer_jid_, JingleMessage::TRANSPORT_INFO, session_id_);
|
| - message.candidates.swap(pending_candidates_);
|
| + DCHECK(pending_transport_info_message_);
|
|
|
| scoped_ptr<IqRequest> request = session_manager_->iq_sender()->SendIq(
|
| - message.ToXml(),
|
| + pending_transport_info_message_->ToXml(),
|
| base::Bind(&JingleSession::OnTransportInfoResponse,
|
| base::Unretained(this)));
|
| + pending_transport_info_message_.reset();
|
| if (request) {
|
| request->SetTimeout(base::TimeDelta::FromSeconds(kTransportInfoTimeout));
|
| transport_info_requests_.push_back(request.release());
|
| @@ -463,9 +491,6 @@ void JingleSession::OnAccept(const JingleMessage& message,
|
| return;
|
| }
|
|
|
| - // In case there is transport information in the accept message.
|
| - ProcessTransportInfo(message);
|
| -
|
| SetState(CONNECTED);
|
|
|
| DCHECK(authenticator_->state() == Authenticator::WAITING_MESSAGE);
|
| @@ -497,6 +522,27 @@ void JingleSession::OnSessionInfo(const JingleMessage& message,
|
| }
|
|
|
| void JingleSession::ProcessTransportInfo(const JingleMessage& message) {
|
| + // Check if the transport information version matches what was negotiated.
|
| + if (message.standard_ice != config_->standard_ice()) {
|
| + LOG(ERROR) << "Received transport-info message in format different from "
|
| + "negotiated.";
|
| + CloseInternal(INCOMPATIBLE_PROTOCOL);
|
| + return;
|
| + }
|
| +
|
| + for (std::list<JingleMessage::IceCredentials>::const_iterator it =
|
| + message.ice_credentials.begin();
|
| + it != message.ice_credentials.end(); ++it) {
|
| + ChannelsMap::iterator channel = channels_.find(it->channel);
|
| + if (channel != channels_.end()) {
|
| + channel->second->SetRemoteCredentials(it->ufrag, it->password);
|
| + } else {
|
| + // Transport info was received before the channel was created.
|
| + // This could happen due to messages being reordered on the wire.
|
| + pending_remote_ice_credentials_.push_back(*it);
|
| + }
|
| + }
|
| +
|
| for (std::list<JingleMessage::NamedCandidate>::const_iterator it =
|
| message.candidates.begin();
|
| it != message.candidates.end(); ++it) {
|
| @@ -555,12 +601,12 @@ void JingleSession::OnTerminate(const JingleMessage& message,
|
| bool JingleSession::InitializeConfigFromDescription(
|
| const ContentDescription* description) {
|
| DCHECK(description);
|
| -
|
| - if (!description->config()->GetFinalConfig(&config_)) {
|
| + config_ = SessionConfig::GetFinalConfig(description->config());
|
| + if (!config_) {
|
| LOG(ERROR) << "session-accept does not specify configuration";
|
| return false;
|
| }
|
| - if (!candidate_config()->IsSupported(config_)) {
|
| + if (!candidate_config()->IsSupported(*config_)) {
|
| LOG(ERROR) << "session-accept specifies an invalid configuration";
|
| return false;
|
| }
|
|
|