Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(709)

Unified Diff: webrtc/libjingle/session/sessionmanager.cc

Issue 1175243003: Remove webrtc/libjingle/{examples,session}. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/libjingle/session/sessionmanager.h ('k') | webrtc/libjingle/session/sessionmanagertask.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/libjingle/session/sessionmanager.cc
diff --git a/webrtc/libjingle/session/sessionmanager.cc b/webrtc/libjingle/session/sessionmanager.cc
deleted file mode 100644
index 25948b25af04da99625949e8117923ddff1354a1..0000000000000000000000000000000000000000
--- a/webrtc/libjingle/session/sessionmanager.cc
+++ /dev/null
@@ -1,1150 +0,0 @@
-/*
- * 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/libjingle/session/sessionmanager.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/libjingle/session/p2ptransportparser.h"
-#include "webrtc/libjingle/session/sessionmessages.h"
-#include "webrtc/libjingle/xmpp/constants.h"
-#include "webrtc/libjingle/xmpp/jid.h"
-#include "webrtc/p2p/base/constants.h"
-
-namespace cricket {
-
-bool BadMessage(const buzz::QName type,
- const std::string& text,
- MessageError* err) {
- err->SetType(type);
- err->SetText(text);
- return false;
-}
-
-
-Session::Session(SessionManager* session_manager,
- const std::string& local_name,
- const std::string& initiator_name,
- const std::string& sid,
- const std::string& content_type,
- SessionClient* client)
- : BaseSession(session_manager->signaling_thread(),
- session_manager->worker_thread(),
- session_manager->port_allocator(),
- sid, content_type, initiator_name == local_name) {
- ASSERT(client != NULL);
- session_manager_ = session_manager;
- local_name_ = local_name;
- initiator_name_ = initiator_name;
- transport_parser_ = new P2PTransportParser();
- client_ = client;
- initiate_acked_ = false;
- current_protocol_ = PROTOCOL_HYBRID;
-}
-
-Session::~Session() {
- delete transport_parser_;
-}
-
-bool Session::Initiate(const std::string& to,
- const SessionDescription* sdesc) {
- ASSERT(signaling_thread()->IsCurrent());
- SessionError error;
-
- // Only from STATE_INIT
- if (state() != STATE_INIT)
- return false;
-
- // Setup for signaling.
- set_remote_name(to);
- set_local_description(sdesc);
- if (!CreateTransportProxies(GetEmptyTransportInfos(sdesc->contents()),
- &error)) {
- LOG(LS_ERROR) << "Could not create transports: " << error.text;
- return false;
- }
-
- if (!SendInitiateMessage(sdesc, &error)) {
- LOG(LS_ERROR) << "Could not send initiate message: " << error.text;
- return false;
- }
-
- // We need to connect transport proxy and impl here so that we can process
- // the TransportDescriptions.
- SpeculativelyConnectAllTransportChannels();
-
- PushdownTransportDescription(CS_LOCAL, CA_OFFER, NULL);
- SetState(Session::STATE_SENTINITIATE);
- return true;
-}
-
-bool Session::Accept(const SessionDescription* sdesc) {
- ASSERT(signaling_thread()->IsCurrent());
-
- // Only if just received initiate
- if (state() != STATE_RECEIVEDINITIATE)
- return false;
-
- // Setup for signaling.
- set_local_description(sdesc);
-
- SessionError error;
- if (!SendAcceptMessage(sdesc, &error)) {
- LOG(LS_ERROR) << "Could not send accept message: " << error.text;
- return false;
- }
- // TODO(juberti): Add BUNDLE support to transport-info messages.
- PushdownTransportDescription(CS_LOCAL, CA_ANSWER, NULL);
- MaybeEnableMuxingSupport(); // Enable transport channel mux if supported.
- SetState(Session::STATE_SENTACCEPT);
- return true;
-}
-
-bool Session::Reject(const std::string& reason) {
- ASSERT(signaling_thread()->IsCurrent());
-
- // Reject is sent in response to an initiate or modify, to reject the
- // request
- if (state() != STATE_RECEIVEDINITIATE && state() != STATE_RECEIVEDMODIFY)
- return false;
-
- SessionError error;
- if (!SendRejectMessage(reason, &error)) {
- LOG(LS_ERROR) << "Could not send reject message: " << error.text;
- return false;
- }
-
- SetState(STATE_SENTREJECT);
- return true;
-}
-
-bool Session::TerminateWithReason(const std::string& reason) {
- ASSERT(signaling_thread()->IsCurrent());
-
- // Either side can terminate, at any time.
- switch (state()) {
- case STATE_SENTTERMINATE:
- case STATE_RECEIVEDTERMINATE:
- return false;
-
- case STATE_SENTREJECT:
- case STATE_RECEIVEDREJECT:
- // We don't need to send terminate if we sent or received a reject...
- // it's implicit.
- break;
-
- default:
- SessionError error;
- if (!SendTerminateMessage(reason, &error)) {
- LOG(LS_ERROR) << "Could not send terminate message: " << error.text;
- return false;
- }
- break;
- }
-
- SetState(STATE_SENTTERMINATE);
- return true;
-}
-
-bool Session::SendInfoMessage(const XmlElements& elems,
- const std::string& remote_name) {
- ASSERT(signaling_thread()->IsCurrent());
- SessionError error;
- if (!SendMessage(ACTION_SESSION_INFO, elems, remote_name, &error)) {
- LOG(LS_ERROR) << "Could not send info message " << error.text;
- return false;
- }
- return true;
-}
-
-bool Session::SendDescriptionInfoMessage(const ContentInfos& contents) {
- XmlElements elems;
- WriteError write_error;
- if (!WriteDescriptionInfo(current_protocol_,
- contents,
- GetContentParsers(),
- &elems, &write_error)) {
- LOG(LS_ERROR) << "Could not write description info message: "
- << write_error.text;
- return false;
- }
- SessionError error;
- if (!SendMessage(ACTION_DESCRIPTION_INFO, elems, &error)) {
- LOG(LS_ERROR) << "Could not send description info message: "
- << error.text;
- return false;
- }
- return true;
-}
-
-TransportInfos Session::GetEmptyTransportInfos(
- const ContentInfos& contents) const {
- TransportInfos tinfos;
- for (ContentInfos::const_iterator content = contents.begin();
- content != contents.end(); ++content) {
- tinfos.push_back(TransportInfo(content->name,
- TransportDescription(transport_type(),
- std::string(),
- std::string())));
- }
- return tinfos;
-}
-
-bool Session::OnRemoteCandidates(
- const TransportInfos& tinfos, ParseError* error) {
- for (TransportInfos::const_iterator tinfo = tinfos.begin();
- tinfo != tinfos.end(); ++tinfo) {
- std::string str_error;
- if (!BaseSession::OnRemoteCandidates(
- tinfo->content_name, tinfo->description.candidates, &str_error)) {
- return BadParse(str_error, error);
- }
- }
- return true;
-}
-
-bool Session::CreateTransportProxies(const TransportInfos& tinfos,
- SessionError* error) {
- for (TransportInfos::const_iterator tinfo = tinfos.begin();
- tinfo != tinfos.end(); ++tinfo) {
- if (tinfo->description.transport_type != transport_type()) {
- error->SetText("No supported transport in offer.");
- return false;
- }
-
- GetOrCreateTransportProxy(tinfo->content_name);
- }
- return true;
-}
-
-TransportParserMap Session::GetTransportParsers() {
- TransportParserMap parsers;
- parsers[transport_type()] = transport_parser_;
- return parsers;
-}
-
-CandidateTranslatorMap Session::GetCandidateTranslators() {
- CandidateTranslatorMap translators;
- // NOTE: This technique makes it impossible to parse G-ICE
- // candidates in session-initiate messages because the channels
- // aren't yet created at that point. Since we don't use candidates
- // in session-initiate messages, we should be OK. Once we switch to
- // ICE, this translation shouldn't be necessary.
- for (TransportMap::const_iterator iter = transport_proxies().begin();
- iter != transport_proxies().end(); ++iter) {
- translators[iter->first] = iter->second;
- }
- return translators;
-}
-
-ContentParserMap Session::GetContentParsers() {
- ContentParserMap parsers;
- parsers[content_type()] = client_;
- // We need to be able parse both RTP-based and SCTP-based Jingle
- // with the same client.
- if (content_type() == NS_JINGLE_RTP) {
- parsers[NS_JINGLE_DRAFT_SCTP] = client_;
- }
- return parsers;
-}
-
-void Session::OnTransportRequestSignaling(Transport* transport) {
- ASSERT(signaling_thread()->IsCurrent());
- TransportProxy* transproxy = GetTransportProxy(transport);
- ASSERT(transproxy != NULL);
- if (transproxy) {
- // Reset candidate allocation status for the transport proxy.
- transproxy->set_candidates_allocated(false);
- }
- SignalRequestSignaling(this);
-}
-
-void Session::OnTransportConnecting(Transport* transport) {
- // This is an indication that we should begin watching the writability
- // state of the transport.
- OnTransportWritable(transport);
-}
-
-void Session::OnTransportWritable(Transport* transport) {
- ASSERT(signaling_thread()->IsCurrent());
-
- // If the transport is not writable, start a timer to make sure that it
- // becomes writable within a reasonable amount of time. If it does not, we
- // terminate since we can't actually send data. If the transport is writable,
- // cancel the timer. Note that writability transitions may occur repeatedly
- // during the lifetime of the session.
- signaling_thread()->Clear(this, MSG_TIMEOUT);
- if (transport->HasChannels() && !transport->writable()) {
- signaling_thread()->PostDelayed(
- session_manager_->session_timeout() * 1000, this, MSG_TIMEOUT);
- }
-}
-
-void Session::OnTransportProxyCandidatesReady(TransportProxy* transproxy,
- const Candidates& candidates) {
- ASSERT(signaling_thread()->IsCurrent());
- if (transproxy != NULL) {
- if (initiator() && !initiate_acked_) {
- // TODO: This is to work around server re-ordering
- // messages. We send the candidates once the session-initiate
- // is acked. Once we have fixed the server to guarantee message
- // order, we can remove this case.
- transproxy->AddUnsentCandidates(candidates);
- } else {
- if (!transproxy->negotiated()) {
- transproxy->AddSentCandidates(candidates);
- }
- SessionError error;
- if (!SendTransportInfoMessage(transproxy, candidates, &error)) {
- LOG(LS_ERROR) << "Could not send transport info message: "
- << error.text;
- return;
- }
- }
- }
-}
-
-void Session::OnIncomingMessage(const SessionMessage& msg) {
- ASSERT(signaling_thread()->IsCurrent());
- ASSERT(state() == STATE_INIT || msg.from == remote_name());
-
- if (current_protocol_== PROTOCOL_HYBRID) {
- if (msg.protocol == PROTOCOL_GINGLE) {
- current_protocol_ = PROTOCOL_GINGLE;
- } else {
- current_protocol_ = PROTOCOL_JINGLE;
- }
- }
-
- bool valid = false;
- MessageError error;
- switch (msg.type) {
- case ACTION_SESSION_INITIATE:
- valid = OnInitiateMessage(msg, &error);
- break;
- case ACTION_SESSION_INFO:
- valid = OnInfoMessage(msg);
- break;
- case ACTION_SESSION_ACCEPT:
- valid = OnAcceptMessage(msg, &error);
- break;
- case ACTION_SESSION_REJECT:
- valid = OnRejectMessage(msg, &error);
- break;
- case ACTION_SESSION_TERMINATE:
- valid = OnTerminateMessage(msg, &error);
- break;
- case ACTION_TRANSPORT_INFO:
- valid = OnTransportInfoMessage(msg, &error);
- break;
- case ACTION_TRANSPORT_ACCEPT:
- valid = OnTransportAcceptMessage(msg, &error);
- break;
- case ACTION_DESCRIPTION_INFO:
- valid = OnDescriptionInfoMessage(msg, &error);
- break;
- default:
- valid = BadMessage(buzz::QN_STANZA_BAD_REQUEST,
- "unknown session message type",
- &error);
- }
-
- if (valid) {
- SendAcknowledgementMessage(msg.stanza);
- } else {
- SignalErrorMessage(this, msg.stanza, error.type,
- "modify", error.text, NULL);
- }
-}
-
-void Session::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
- const buzz::XmlElement* response_stanza,
- const SessionMessage& msg) {
- ASSERT(signaling_thread()->IsCurrent());
-
- if (msg.type == ACTION_SESSION_INITIATE) {
- OnInitiateAcked();
- }
-}
-
-void Session::OnInitiateAcked() {
- // TODO: This is to work around server re-ordering
- // messages. We send the candidates once the session-initiate
- // is acked. Once we have fixed the server to guarantee message
- // order, we can remove this case.
- if (!initiate_acked_) {
- initiate_acked_ = true;
- SessionError error;
- SendAllUnsentTransportInfoMessages(&error);
- }
-}
-
-void Session::OnFailedSend(const buzz::XmlElement* orig_stanza,
- const buzz::XmlElement* error_stanza) {
- ASSERT(signaling_thread()->IsCurrent());
-
- SessionMessage msg;
- ParseError parse_error;
- if (!ParseSessionMessage(orig_stanza, &msg, &parse_error)) {
- LOG(LS_ERROR) << "Error parsing failed send: " << parse_error.text
- << ":" << orig_stanza;
- return;
- }
-
- // If the error is a session redirect, call OnRedirectError, which will
- // continue the session with a new remote JID.
- SessionRedirect redirect;
- if (FindSessionRedirect(error_stanza, &redirect)) {
- SessionError error;
- if (!OnRedirectError(redirect, &error)) {
- // TODO: Should we send a message back? The standard
- // says nothing about it.
- std::ostringstream desc;
- desc << "Failed to redirect: " << error.text;
- LOG(LS_ERROR) << desc.str();
- SetError(ERROR_RESPONSE, desc.str());
- }
- return;
- }
-
- std::string error_type = "cancel";
-
- const buzz::XmlElement* error = error_stanza->FirstNamed(buzz::QN_ERROR);
- if (error) {
- error_type = error->Attr(buzz::QN_TYPE);
-
- LOG(LS_ERROR) << "Session error:\n" << error->Str() << "\n"
- << "in response to:\n" << orig_stanza->Str();
- } else {
- // don't crash if <error> is missing
- LOG(LS_ERROR) << "Session error without <error/> element, ignoring";
- return;
- }
-
- if (msg.type == ACTION_TRANSPORT_INFO) {
- // Transport messages frequently generate errors because they are sent right
- // when we detect a network failure. For that reason, we ignore such
- // errors, because if we do not establish writability again, we will
- // terminate anyway. The exceptions are transport-specific error tags,
- // which we pass on to the respective transport.
- } else if ((error_type != "continue") && (error_type != "wait")) {
- // We do not set an error if the other side said it is okay to continue
- // (possibly after waiting). These errors can be ignored.
- SetError(ERROR_RESPONSE, "");
- }
-}
-
-bool Session::OnInitiateMessage(const SessionMessage& msg,
- MessageError* error) {
- if (!CheckState(STATE_INIT, error))
- return false;
-
- SessionInitiate init;
- if (!ParseSessionInitiate(msg.protocol, msg.action_elem,
- GetContentParsers(), GetTransportParsers(),
- GetCandidateTranslators(),
- &init, error))
- return false;
-
- SessionError session_error;
- if (!CreateTransportProxies(init.transports, &session_error)) {
- return BadMessage(buzz::QN_STANZA_NOT_ACCEPTABLE,
- session_error.text, error);
- }
-
- set_remote_name(msg.from);
- set_initiator_name(msg.initiator);
- set_remote_description(new SessionDescription(init.ClearContents(),
- init.transports,
- init.groups));
- // Updating transport with TransportDescription.
- PushdownTransportDescription(CS_REMOTE, CA_OFFER, NULL);
- SetState(STATE_RECEIVEDINITIATE);
-
- // Users of Session may listen to state change and call Reject().
- if (state() != STATE_SENTREJECT) {
- if (!OnRemoteCandidates(init.transports, error))
- return false;
-
- // TODO(juberti): Auto-generate and push down the local transport answer.
- // This is necessary for trickling to work with RFC 5245 ICE.
- }
- return true;
-}
-
-bool Session::OnAcceptMessage(const SessionMessage& msg, MessageError* error) {
- if (!CheckState(STATE_SENTINITIATE, error))
- return false;
-
- SessionAccept accept;
- if (!ParseSessionAccept(msg.protocol, msg.action_elem,
- GetContentParsers(), GetTransportParsers(),
- GetCandidateTranslators(),
- &accept, error)) {
- return false;
- }
-
- // If we get an accept, we can assume the initiate has been
- // received, even if we haven't gotten an IQ response.
- OnInitiateAcked();
-
- set_remote_description(new SessionDescription(accept.ClearContents(),
- accept.transports,
- accept.groups));
- // Updating transport with TransportDescription.
- PushdownTransportDescription(CS_REMOTE, CA_ANSWER, NULL);
- MaybeEnableMuxingSupport(); // Enable transport channel mux if supported.
- SetState(STATE_RECEIVEDACCEPT);
-
- if (!OnRemoteCandidates(accept.transports, error))
- return false;
-
- return true;
-}
-
-bool Session::OnRejectMessage(const SessionMessage& msg, MessageError* error) {
- if (!CheckState(STATE_SENTINITIATE, error))
- return false;
-
- SetState(STATE_RECEIVEDREJECT);
- return true;
-}
-
-bool Session::OnInfoMessage(const SessionMessage& msg) {
- SignalInfoMessage(this, msg.action_elem);
- return true;
-}
-
-bool Session::OnTerminateMessage(const SessionMessage& msg,
- MessageError* error) {
- SessionTerminate term;
- if (!ParseSessionTerminate(msg.protocol, msg.action_elem, &term, error))
- return false;
-
- SignalReceivedTerminateReason(this, term.reason);
- if (term.debug_reason != buzz::STR_EMPTY) {
- LOG(LS_VERBOSE) << "Received error on call: " << term.debug_reason;
- }
-
- SetState(STATE_RECEIVEDTERMINATE);
- return true;
-}
-
-bool Session::OnTransportInfoMessage(const SessionMessage& msg,
- MessageError* error) {
- TransportInfos tinfos;
- if (!ParseTransportInfos(msg.protocol, msg.action_elem,
- initiator_description()->contents(),
- GetTransportParsers(), GetCandidateTranslators(),
- &tinfos, error))
- return false;
-
- if (!OnRemoteCandidates(tinfos, error))
- return false;
-
- return true;
-}
-
-bool Session::OnTransportAcceptMessage(const SessionMessage& msg,
- MessageError* error) {
- // TODO: Currently here only for compatibility with
- // Gingle 1.1 clients (notably, Google Voice).
- return true;
-}
-
-bool Session::OnDescriptionInfoMessage(const SessionMessage& msg,
- MessageError* error) {
- if (!CheckState(STATE_INPROGRESS, error))
- return false;
-
- DescriptionInfo description_info;
- if (!ParseDescriptionInfo(msg.protocol, msg.action_elem,
- GetContentParsers(), GetTransportParsers(),
- GetCandidateTranslators(),
- &description_info, error)) {
- return false;
- }
-
- ContentInfos& updated_contents = description_info.contents;
-
- // TODO: Currently, reflector sends back
- // video stream updates even for an audio-only call, which causes
- // this to fail. Put this back once reflector is fixed.
- //
- // ContentInfos::iterator it;
- // First, ensure all updates are valid before modifying remote_description_.
- // for (it = updated_contents.begin(); it != updated_contents.end(); ++it) {
- // if (remote_description()->GetContentByName(it->name) == NULL) {
- // return false;
- // }
- // }
-
- // TODO: We used to replace contents from an update, but
- // that no longer works with partial updates. We need to figure out
- // a way to merge patial updates into contents. For now, users of
- // Session should listen to SignalRemoteDescriptionUpdate and handle
- // updates. They should not expect remote_description to be the
- // latest value.
- //
- // for (it = updated_contents.begin(); it != updated_contents.end(); ++it) {
- // remote_description()->RemoveContentByName(it->name);
- // remote_description()->AddContent(it->name, it->type, it->description);
- // }
- // }
-
- SignalRemoteDescriptionUpdate(this, updated_contents);
- return true;
-}
-
-bool BareJidsEqual(const std::string& name1,
- const std::string& name2) {
- buzz::Jid jid1(name1);
- buzz::Jid jid2(name2);
-
- return jid1.IsValid() && jid2.IsValid() && jid1.BareEquals(jid2);
-}
-
-bool Session::OnRedirectError(const SessionRedirect& redirect,
- SessionError* error) {
- MessageError message_error;
- if (!CheckState(STATE_SENTINITIATE, &message_error)) {
- return BadWrite(message_error.text, error);
- }
-
- if (!BareJidsEqual(remote_name(), redirect.target))
- return BadWrite("Redirection not allowed: must be the same bare jid.",
- error);
-
- // When we receive a redirect, we point the session at the new JID
- // and resend the candidates.
- set_remote_name(redirect.target);
- return (SendInitiateMessage(local_description(), error) &&
- ResendAllTransportInfoMessages(error));
-}
-
-bool Session::CheckState(State expected, MessageError* error) {
- if (state() != expected) {
- // The server can deliver messages out of order/repeated for various
- // reasons. For example, if the server does not recive our iq response,
- // it could assume that the iq it sent was lost, and will then send
- // it again. Ideally, we should implement reliable messaging with
- // duplicate elimination.
- return BadMessage(buzz::QN_STANZA_NOT_ALLOWED,
- "message not allowed in current state",
- error);
- }
- return true;
-}
-
-void Session::SetError(Error error, const std::string& error_desc) {
- BaseSession::SetError(error, error_desc);
- if (error != ERROR_NONE)
- signaling_thread()->Post(this, MSG_ERROR);
-}
-
-void Session::OnMessage(rtc::Message* pmsg) {
- // preserve this because BaseSession::OnMessage may modify it
- State orig_state = state();
-
- BaseSession::OnMessage(pmsg);
-
- switch (pmsg->message_id) {
- case MSG_ERROR:
- TerminateWithReason(STR_TERMINATE_ERROR);
- break;
-
- case MSG_STATE:
- switch (orig_state) {
- case STATE_SENTREJECT:
- case STATE_RECEIVEDREJECT:
- // Assume clean termination.
- Terminate();
- break;
-
- case STATE_SENTTERMINATE:
- case STATE_RECEIVEDTERMINATE:
- session_manager_->DestroySession(this);
- break;
-
- default:
- // Explicitly ignoring some states here.
- break;
- }
- break;
- }
-}
-
-bool Session::SendInitiateMessage(const SessionDescription* sdesc,
- SessionError* error) {
- SessionInitiate init;
- init.contents = sdesc->contents();
- init.transports = GetEmptyTransportInfos(init.contents);
- init.groups = sdesc->groups();
- return SendMessage(ACTION_SESSION_INITIATE, init, error);
-}
-
-bool Session::WriteSessionAction(
- SignalingProtocol protocol, const SessionInitiate& init,
- XmlElements* elems, WriteError* error) {
- return WriteSessionInitiate(protocol, init.contents, init.transports,
- GetContentParsers(), GetTransportParsers(),
- GetCandidateTranslators(), init.groups,
- elems, error);
-}
-
-bool Session::SendAcceptMessage(const SessionDescription* sdesc,
- SessionError* error) {
- XmlElements elems;
- if (!WriteSessionAccept(current_protocol_,
- sdesc->contents(),
- GetEmptyTransportInfos(sdesc->contents()),
- GetContentParsers(), GetTransportParsers(),
- GetCandidateTranslators(), sdesc->groups(),
- &elems, error)) {
- return false;
- }
- return SendMessage(ACTION_SESSION_ACCEPT, elems, error);
-}
-
-bool Session::SendRejectMessage(const std::string& reason,
- SessionError* error) {
- SessionTerminate term(reason);
- return SendMessage(ACTION_SESSION_REJECT, term, error);
-}
-
-bool Session::SendTerminateMessage(const std::string& reason,
- SessionError* error) {
- SessionTerminate term(reason);
- return SendMessage(ACTION_SESSION_TERMINATE, term, error);
-}
-
-bool Session::WriteSessionAction(SignalingProtocol protocol,
- const SessionTerminate& term,
- XmlElements* elems, WriteError* error) {
- WriteSessionTerminate(protocol, term, elems);
- return true;
-}
-
-bool Session::SendTransportInfoMessage(const TransportInfo& tinfo,
- SessionError* error) {
- return SendMessage(ACTION_TRANSPORT_INFO, tinfo, error);
-}
-
-bool Session::SendTransportInfoMessage(const TransportProxy* transproxy,
- const Candidates& candidates,
- SessionError* error) {
- return SendTransportInfoMessage(TransportInfo(transproxy->content_name(),
- TransportDescription(transproxy->type(), std::vector<std::string>(),
- std::string(), std::string(), ICEMODE_FULL,
- CONNECTIONROLE_NONE, NULL, candidates)), error);
-}
-
-bool Session::WriteSessionAction(SignalingProtocol protocol,
- const TransportInfo& tinfo,
- XmlElements* elems, WriteError* error) {
- TransportInfos tinfos;
- tinfos.push_back(tinfo);
- return WriteTransportInfos(protocol, tinfos,
- GetTransportParsers(), GetCandidateTranslators(),
- elems, error);
-}
-
-bool Session::ResendAllTransportInfoMessages(SessionError* error) {
- for (TransportMap::const_iterator iter = transport_proxies().begin();
- iter != transport_proxies().end(); ++iter) {
- TransportProxy* transproxy = iter->second;
- if (transproxy->sent_candidates().size() > 0) {
- if (!SendTransportInfoMessage(
- transproxy, transproxy->sent_candidates(), error)) {
- LOG(LS_ERROR) << "Could not resend transport info messages: "
- << error->text;
- return false;
- }
- transproxy->ClearSentCandidates();
- }
- }
- return true;
-}
-
-bool Session::SendAllUnsentTransportInfoMessages(SessionError* error) {
- for (TransportMap::const_iterator iter = transport_proxies().begin();
- iter != transport_proxies().end(); ++iter) {
- TransportProxy* transproxy = iter->second;
- if (transproxy->unsent_candidates().size() > 0) {
- if (!SendTransportInfoMessage(
- transproxy, transproxy->unsent_candidates(), error)) {
- LOG(LS_ERROR) << "Could not send unsent transport info messages: "
- << error->text;
- return false;
- }
- transproxy->ClearUnsentCandidates();
- }
- }
- return true;
-}
-
-bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
- SessionError* error) {
- return SendMessage(type, action_elems, remote_name(), error);
-}
-
-bool Session::SendMessage(ActionType type, const XmlElements& action_elems,
- const std::string& remote_name, SessionError* error) {
- rtc::scoped_ptr<buzz::XmlElement> stanza(
- new buzz::XmlElement(buzz::QN_IQ));
-
- SessionMessage msg(current_protocol_, type, id(), initiator_name());
- msg.to = remote_name;
- WriteSessionMessage(msg, action_elems, stanza.get());
-
- SignalOutgoingMessage(this, stanza.get());
- return true;
-}
-
-template <typename Action>
-bool Session::SendMessage(ActionType type, const Action& action,
- SessionError* error) {
- rtc::scoped_ptr<buzz::XmlElement> stanza(
- new buzz::XmlElement(buzz::QN_IQ));
- if (!WriteActionMessage(type, action, stanza.get(), error))
- return false;
-
- SignalOutgoingMessage(this, stanza.get());
- return true;
-}
-
-template <typename Action>
-bool Session::WriteActionMessage(ActionType type, const Action& action,
- buzz::XmlElement* stanza,
- WriteError* error) {
- if (current_protocol_ == PROTOCOL_HYBRID) {
- if (!WriteActionMessage(PROTOCOL_JINGLE, type, action, stanza, error))
- return false;
- if (!WriteActionMessage(PROTOCOL_GINGLE, type, action, stanza, error))
- return false;
- } else {
- if (!WriteActionMessage(current_protocol_, type, action, stanza, error))
- return false;
- }
- return true;
-}
-
-template <typename Action>
-bool Session::WriteActionMessage(SignalingProtocol protocol,
- ActionType type, const Action& action,
- buzz::XmlElement* stanza, WriteError* error) {
- XmlElements action_elems;
- if (!WriteSessionAction(protocol, action, &action_elems, error))
- return false;
-
- SessionMessage msg(protocol, type, id(), initiator_name());
- msg.to = remote_name();
-
- WriteSessionMessage(msg, action_elems, stanza);
- return true;
-}
-
-void Session::SendAcknowledgementMessage(const buzz::XmlElement* stanza) {
- rtc::scoped_ptr<buzz::XmlElement> ack(
- new buzz::XmlElement(buzz::QN_IQ));
- ack->SetAttr(buzz::QN_TO, remote_name());
- ack->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
- ack->SetAttr(buzz::QN_TYPE, "result");
-
- SignalOutgoingMessage(this, ack.get());
-}
-
-SessionManager::SessionManager(PortAllocator *allocator,
- rtc::Thread *worker) {
- allocator_ = allocator;
- signaling_thread_ = rtc::Thread::Current();
- if (worker == NULL) {
- worker_thread_ = rtc::Thread::Current();
- } else {
- worker_thread_ = worker;
- }
- timeout_ = 50;
-}
-
-SessionManager::~SessionManager() {
- // Note: Session::Terminate occurs asynchronously, so it's too late to
- // delete them now. They better be all gone.
- ASSERT(session_map_.empty());
- // TerminateAll();
- SignalDestroyed();
-}
-
-void SessionManager::AddClient(const std::string& content_type,
- SessionClient* client) {
- ASSERT(client_map_.find(content_type) == client_map_.end());
- client_map_[content_type] = client;
-}
-
-void SessionManager::RemoveClient(const std::string& content_type) {
- ClientMap::iterator iter = client_map_.find(content_type);
- ASSERT(iter != client_map_.end());
- client_map_.erase(iter);
-}
-
-SessionClient* SessionManager::GetClient(const std::string& content_type) {
- ClientMap::iterator iter = client_map_.find(content_type);
- return (iter != client_map_.end()) ? iter->second : NULL;
-}
-
-Session* SessionManager::CreateSession(const std::string& local_name,
- const std::string& content_type) {
- std::string id;
- return CreateSession(id, local_name, content_type);
-}
-
-Session* SessionManager::CreateSession(const std::string& id,
- const std::string& local_name,
- const std::string& content_type) {
- std::string sid =
- id.empty() ? rtc::ToString(rtc::CreateRandomId64()) : id;
- return CreateSession(local_name, local_name, sid, content_type, false);
-}
-
-Session* SessionManager::CreateSession(
- const std::string& local_name, const std::string& initiator_name,
- const std::string& sid, const std::string& content_type,
- bool received_initiate) {
- SessionClient* client = GetClient(content_type);
- ASSERT(client != NULL);
-
- Session* session = new Session(this, local_name, initiator_name,
- sid, content_type, client);
- session->SetIdentity(transport_desc_factory_.identity());
- session_map_[session->id()] = session;
- session->SignalRequestSignaling.connect(
- this, &SessionManager::OnRequestSignaling);
- session->SignalOutgoingMessage.connect(
- this, &SessionManager::OnOutgoingMessage);
- session->SignalErrorMessage.connect(this, &SessionManager::OnErrorMessage);
- SignalSessionCreate(session, received_initiate);
- session->client()->OnSessionCreate(session, received_initiate);
- return session;
-}
-
-void SessionManager::DestroySession(Session* session) {
- if (session != NULL) {
- SessionMap::iterator it = session_map_.find(session->id());
- if (it != session_map_.end()) {
- SignalSessionDestroy(session);
- session->client()->OnSessionDestroy(session);
- session_map_.erase(it);
- delete session;
- }
- }
-}
-
-Session* SessionManager::GetSession(const std::string& sid) {
- SessionMap::iterator it = session_map_.find(sid);
- if (it != session_map_.end())
- return it->second;
- return NULL;
-}
-
-void SessionManager::TerminateAll() {
- while (session_map_.begin() != session_map_.end()) {
- Session* session = session_map_.begin()->second;
- session->Terminate();
- }
-}
-
-bool SessionManager::IsSessionMessage(const buzz::XmlElement* stanza) {
- return cricket::IsSessionMessage(stanza);
-}
-
-Session* SessionManager::FindSession(const std::string& sid,
- const std::string& remote_name) {
- SessionMap::iterator iter = session_map_.find(sid);
- if (iter == session_map_.end())
- return NULL;
-
- Session* session = iter->second;
- if (buzz::Jid(remote_name) != buzz::Jid(session->remote_name()))
- return NULL;
-
- return session;
-}
-
-void SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {
- SessionMessage msg;
- ParseError error;
-
- if (!ParseSessionMessage(stanza, &msg, &error)) {
- SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- error.text, NULL);
- return;
- }
-
- Session* session = FindSession(msg.sid, msg.from);
- if (session) {
- session->OnIncomingMessage(msg);
- return;
- }
- if (msg.type != ACTION_SESSION_INITIATE) {
- SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- "unknown session", NULL);
- return;
- }
-
- std::string content_type;
- if (!ParseContentType(msg.protocol, msg.action_elem,
- &content_type, &error)) {
- SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- error.text, NULL);
- return;
- }
-
- if (!GetClient(content_type)) {
- SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",
- "unknown content type: " + content_type, NULL);
- return;
- }
-
- session = CreateSession(msg.to, msg.initiator, msg.sid,
- content_type, true);
- session->OnIncomingMessage(msg);
-}
-
-void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,
- const buzz::XmlElement* response_stanza) {
- if (orig_stanza == NULL || response_stanza == NULL) {
- return;
- }
-
- SessionMessage msg;
- ParseError error;
- if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
- LOG(LS_WARNING) << "Error parsing incoming response: " << error.text
- << ":" << orig_stanza;
- return;
- }
-
- Session* session = FindSession(msg.sid, msg.to);
- if (!session) {
- // Also try the QN_FROM in the response stanza, in case we sent the request
- // to a bare JID but got the response from a full JID.
- std::string ack_from = response_stanza->Attr(buzz::QN_FROM);
- session = FindSession(msg.sid, ack_from);
- }
- if (session) {
- session->OnIncomingResponse(orig_stanza, response_stanza, msg);
- }
-}
-
-void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,
- const buzz::XmlElement* error_stanza) {
- SessionMessage msg;
- ParseError error;
- if (!ParseSessionMessage(orig_stanza, &msg, &error)) {
- return; // TODO: log somewhere?
- }
-
- Session* session = FindSession(msg.sid, msg.to);
- if (session) {
- rtc::scoped_ptr<buzz::XmlElement> synthetic_error;
- if (!error_stanza) {
- // A failed send is semantically equivalent to an error response, so we
- // can just turn the former into the latter.
- synthetic_error.reset(
- CreateErrorMessage(orig_stanza, buzz::QN_STANZA_ITEM_NOT_FOUND,
- "cancel", "Recipient did not respond", NULL));
- error_stanza = synthetic_error.get();
- }
-
- session->OnFailedSend(orig_stanza, error_stanza);
- }
-}
-
-void SessionManager::SendErrorMessage(const buzz::XmlElement* stanza,
- const buzz::QName& name,
- const std::string& type,
- const std::string& text,
- const buzz::XmlElement* extra_info) {
- rtc::scoped_ptr<buzz::XmlElement> msg(
- CreateErrorMessage(stanza, name, type, text, extra_info));
- SignalOutgoingMessage(this, msg.get());
-}
-
-buzz::XmlElement* SessionManager::CreateErrorMessage(
- const buzz::XmlElement* stanza,
- const buzz::QName& name,
- const std::string& type,
- const std::string& text,
- const buzz::XmlElement* extra_info) {
- buzz::XmlElement* iq = new buzz::XmlElement(buzz::QN_IQ);
- iq->SetAttr(buzz::QN_TO, stanza->Attr(buzz::QN_FROM));
- iq->SetAttr(buzz::QN_ID, stanza->Attr(buzz::QN_ID));
- iq->SetAttr(buzz::QN_TYPE, "error");
-
- CopyXmlChildren(stanza, iq);
-
- buzz::XmlElement* error = new buzz::XmlElement(buzz::QN_ERROR);
- error->SetAttr(buzz::QN_TYPE, type);
- iq->AddElement(error);
-
- // If the error name is not in the standard namespace, we have to first add
- // some error from that namespace.
- if (name.Namespace() != buzz::NS_STANZA) {
- error->AddElement(
- new buzz::XmlElement(buzz::QN_STANZA_UNDEFINED_CONDITION));
- }
- error->AddElement(new buzz::XmlElement(name));
-
- if (extra_info)
- error->AddElement(new buzz::XmlElement(*extra_info));
-
- if (text.size() > 0) {
- // It's okay to always use English here. This text is for debugging
- // purposes only.
- buzz::XmlElement* text_elem = new buzz::XmlElement(buzz::QN_STANZA_TEXT);
- text_elem->SetAttr(buzz::QN_XML_LANG, "en");
- text_elem->SetBodyText(text);
- error->AddElement(text_elem);
- }
-
- // TODO: Should we include error codes as well for SIP compatibility?
-
- return iq;
-}
-
-void SessionManager::OnOutgoingMessage(Session* session,
- const buzz::XmlElement* stanza) {
- SignalOutgoingMessage(this, stanza);
-}
-
-void SessionManager::OnErrorMessage(BaseSession* session,
- const buzz::XmlElement* stanza,
- const buzz::QName& name,
- const std::string& type,
- const std::string& text,
- const buzz::XmlElement* extra_info) {
- SendErrorMessage(stanza, name, type, text, extra_info);
-}
-
-void SessionManager::OnSignalingReady() {
- for (SessionMap::iterator it = session_map_.begin();
- it != session_map_.end();
- ++it) {
- it->second->OnSignalingReady();
- }
-}
-
-void SessionManager::OnRequestSignaling(Session* session) {
- SignalRequestSignaling();
-}
-
-} // namespace cricket
« no previous file with comments | « webrtc/libjingle/session/sessionmanager.h ('k') | webrtc/libjingle/session/sessionmanagertask.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698