blob: 5e5a88f8d1d0975a9972296d22af1ebcb3e7880b [file] [log] [blame]
/*
* Copyright 2004 The WebRTC Project Authors. All rights reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/p2p/base/session.h"
#include "webrtc/base/bind.h"
#include "webrtc/base/common.h"
#include "webrtc/base/helpers.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/scoped_ptr.h"
#include "webrtc/base/stringencode.h"
#include "webrtc/base/sslstreamadapter.h"
#include "webrtc/p2p/base/transport.h"
#include "webrtc/p2p/base/transportinfo.h"
#include "webrtc/p2p/base/transportcontroller.h"
#include "webrtc/p2p/base/constants.h"
namespace cricket {
using rtc::Bind;
std::string BaseSession::StateToString(State state) {
switch (state) {
case STATE_INIT:
return "STATE_INIT";
case STATE_SENTINITIATE:
return "STATE_SENTINITIATE";
case STATE_RECEIVEDINITIATE:
return "STATE_RECEIVEDINITIATE";
case STATE_SENTPRACCEPT:
return "STATE_SENTPRACCEPT";
case STATE_SENTACCEPT:
return "STATE_SENTACCEPT";
case STATE_RECEIVEDPRACCEPT:
return "STATE_RECEIVEDPRACCEPT";
case STATE_RECEIVEDACCEPT:
return "STATE_RECEIVEDACCEPT";
case STATE_SENTMODIFY:
return "STATE_SENTMODIFY";
case STATE_RECEIVEDMODIFY:
return "STATE_RECEIVEDMODIFY";
case STATE_SENTREJECT:
return "STATE_SENTREJECT";
case STATE_RECEIVEDREJECT:
return "STATE_RECEIVEDREJECT";
case STATE_SENTREDIRECT:
return "STATE_SENTREDIRECT";
case STATE_SENTTERMINATE:
return "STATE_SENTTERMINATE";
case STATE_RECEIVEDTERMINATE:
return "STATE_RECEIVEDTERMINATE";
case STATE_INPROGRESS:
return "STATE_INPROGRESS";
case STATE_DEINIT:
return "STATE_DEINIT";
default:
break;
}
return "STATE_" + rtc::ToString(state);
}
BaseSession::BaseSession(rtc::Thread* signaling_thread,
rtc::Thread* worker_thread,
PortAllocator* port_allocator,
const std::string& sid,
bool initiator)
: state_(STATE_INIT),
error_(ERROR_NONE),
signaling_thread_(signaling_thread),
worker_thread_(worker_thread),
port_allocator_(port_allocator),
sid_(sid),
transport_controller_(new TransportController(signaling_thread,
worker_thread,
port_allocator)) {
ASSERT(signaling_thread->IsCurrent());
set_initiator(initiator);
}
BaseSession::~BaseSession() {
ASSERT(signaling_thread()->IsCurrent());
ASSERT(state_ != STATE_DEINIT);
LogState(state_, STATE_DEINIT);
state_ = STATE_DEINIT;
SignalState(this, state_);
}
const SessionDescription* BaseSession::local_description() const {
// TODO(tommi): Assert on thread correctness.
return local_description_.get();
}
const SessionDescription* BaseSession::remote_description() const {
// TODO(tommi): Assert on thread correctness.
return remote_description_.get();
}
SessionDescription* BaseSession::remote_description() {
// TODO(tommi): Assert on thread correctness.
return remote_description_.get();
}
void BaseSession::set_local_description(const SessionDescription* sdesc) {
// TODO(tommi): Assert on thread correctness.
if (sdesc != local_description_.get())
local_description_.reset(sdesc);
}
void BaseSession::set_remote_description(SessionDescription* sdesc) {
// TODO(tommi): Assert on thread correctness.
if (sdesc != remote_description_)
remote_description_.reset(sdesc);
}
void BaseSession::set_initiator(bool initiator) {
initiator_ = initiator;
IceRole ice_role = initiator ? ICEROLE_CONTROLLING : ICEROLE_CONTROLLED;
transport_controller_->SetIceRole(ice_role);
}
const SessionDescription* BaseSession::initiator_description() const {
// TODO(tommi): Assert on thread correctness.
return initiator_ ? local_description_.get() : remote_description_.get();
}
bool BaseSession::PushdownTransportDescription(ContentSource source,
ContentAction action,
std::string* error_desc) {
ASSERT(signaling_thread()->IsCurrent());
if (source == CS_LOCAL) {
return PushdownLocalTransportDescription(local_description(),
action,
error_desc);
}
return PushdownRemoteTransportDescription(remote_description(),
action,
error_desc);
}
bool BaseSession::PushdownLocalTransportDescription(
const SessionDescription* sdesc,
ContentAction action,
std::string* err) {
ASSERT(signaling_thread()->IsCurrent());
if (!sdesc) {
return false;
}
for (const TransportInfo& tinfo : sdesc->transport_infos()) {
if (!transport_controller_->SetLocalTransportDescription(
tinfo.content_name, tinfo.description, action, err)) {
return false;
}
}
return true;
}
bool BaseSession::PushdownRemoteTransportDescription(
const SessionDescription* sdesc,
ContentAction action,
std::string* err) {
ASSERT(signaling_thread()->IsCurrent());
if (!sdesc) {
return false;
}
for (const TransportInfo& tinfo : sdesc->transport_infos()) {
if (!transport_controller_->SetRemoteTransportDescription(
tinfo.content_name, tinfo.description, action, err)) {
return false;
}
}
return true;
}
void BaseSession::SetState(State state) {
ASSERT(signaling_thread_->IsCurrent());
if (state != state_) {
LogState(state_, state);
state_ = state;
SignalState(this, state_);
signaling_thread_->Post(this, MSG_STATE);
}
}
void BaseSession::SetError(Error error, const std::string& error_desc) {
ASSERT(signaling_thread_->IsCurrent());
if (error != error_) {
error_ = error;
error_desc_ = error_desc;
SignalError(this, error);
}
}
void BaseSession::SetIceConfig(const IceConfig& config) {
transport_controller_->SetIceConfig(config);
}
void BaseSession::MaybeStartGathering() {
transport_controller_->MaybeStartGathering();
}
void BaseSession::LogState(State old_state, State new_state) {
LOG(LS_INFO) << "Session:" << id()
<< " Old state:" << StateToString(old_state)
<< " New state:" << StateToString(new_state);
}
// static
bool BaseSession::GetTransportDescription(const SessionDescription* description,
const std::string& content_name,
TransportDescription* tdesc) {
if (!description || !tdesc) {
return false;
}
const TransportInfo* transport_info =
description->GetTransportInfoByName(content_name);
if (!transport_info) {
return false;
}
*tdesc = transport_info->description;
return true;
}
void BaseSession::OnMessage(rtc::Message *pmsg) {
switch (pmsg->message_id) {
case MSG_TIMEOUT:
// Session timeout has occured.
SetError(ERROR_TIME, "Session timeout has occured.");
break;
case MSG_STATE:
switch (state_) {
case STATE_SENTACCEPT:
case STATE_RECEIVEDACCEPT:
SetState(STATE_INPROGRESS);
break;
default:
// Explicitly ignoring some states here.
break;
}
break;
}
}
} // namespace cricket