⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sessionmanager.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
字号:
/* * libjingle * Copyright 2004--2005, Google Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * *  1. Redistributions of source code must retain the above copyright notice, *     this list of conditions and the following disclaimer. *  2. Redistributions in binary form must reproduce the above copyright notice, *     this list of conditions and the following disclaimer in the documentation *     and/or other materials provided with the distribution. *  3. The name of the author may not be used to endorse or promote products *     derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#include "talk/p2p/base/sessionmanager.h"#include "talk/base/common.h"#include "talk/base/helpers.h"#include "talk/p2p/base/constants.h"#include "talk/xmpp/constants.h"#include "talk/xmpp/jid.h"namespace cricket {SessionManager::SessionManager(PortAllocator *allocator,                                talk_base::Thread *worker) {  allocator_ = allocator;  signaling_thread_ = talk_base::Thread::Current();  if (worker == NULL) {    worker_thread_ = talk_base::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();}void SessionManager::AddClient(const std::string& session_type,                               SessionClient* client) {  ASSERT(client_map_.find(session_type) == client_map_.end());  client_map_[session_type] = client;}void SessionManager::RemoveClient(const std::string& session_type) {  ClientMap::iterator iter = client_map_.find(session_type);  ASSERT(iter != client_map_.end());  client_map_.erase(iter);}SessionClient* SessionManager::GetClient(const std::string& session_type) {  ClientMap::iterator iter = client_map_.find(session_type);  return (iter != client_map_.end()) ? iter->second : NULL;}Session *SessionManager::CreateSession(const std::string& name,                                       const std::string& session_type) {  return CreateSession(name, SessionID(name, CreateRandomId()), session_type,                       false);}Session *SessionManager::CreateSession(    const std::string &name, const SessionID& id,    const std::string& session_type, bool received_initiate) {  SessionClient* client = GetClient(session_type);  ASSERT(client != NULL);  Session *session = new Session(this, name, id, session_type, client);  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 SessionID& id) {  SessionMap::iterator it = session_map_.find(id);  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) {  if (stanza->Name() != buzz::QN_IQ)    return false;  if (!stanza->HasAttr(buzz::QN_TYPE))    return false;  if (stanza->Attr(buzz::QN_TYPE) != buzz::STR_SET)    return false;  const buzz::XmlElement* session = stanza->FirstNamed(QN_SESSION);  if (!session)    return false;  if (!session->HasAttr(buzz::QN_TYPE))    return false;  if (!session->HasAttr(buzz::QN_ID) || !session->HasAttr(QN_INITIATOR))    return false;  return true;}Session* SessionManager::FindSessionForStanza(const buzz::XmlElement* stanza,                                               bool incoming) {  const buzz::XmlElement* session_xml = stanza->FirstNamed(QN_SESSION);  ASSERT(session_xml != NULL);  SessionID id;  id.set_id_str(session_xml->Attr(buzz::QN_ID));  id.set_initiator(session_xml->Attr(QN_INITIATOR));  // Pass this message to the session in question.  SessionMap::iterator iter = session_map_.find(id);  if (iter == session_map_.end())    return NULL;  Session* session = iter->second;  // match on "from"? or "to"?  buzz::QName attr = buzz::QN_TO;  if (incoming) {    attr = buzz::QN_FROM;  }  buzz::Jid remote(session->remote_name());  buzz::Jid match(stanza->Attr(attr));  if (remote == match) {    return session;  }  return NULL;}void SessionManager::OnIncomingMessage(const buzz::XmlElement* stanza) {  ASSERT(stanza->Attr(buzz::QN_TYPE) == buzz::STR_SET);  Session* session = FindSessionForStanza(stanza, true);  if (session) {    session->OnIncomingMessage(stanza);    return;  }  const buzz::XmlElement* session_xml = stanza->FirstNamed(QN_SESSION);  ASSERT(session_xml != NULL);  if (session_xml->Attr(buzz::QN_TYPE) == "initiate") {    std::string session_type = FindClient(session_xml);    if (session_type.size() == 0) {      SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",                       "unknown session description type", NULL);    } else {      SessionID id;      id.set_id_str(session_xml->Attr(buzz::QN_ID));      id.set_initiator(session_xml->Attr(QN_INITIATOR));      session = CreateSession(stanza->Attr(buzz::QN_TO),                               id,                              session_type,  true);      session->OnIncomingMessage(stanza);      // If we haven't rejected, and we haven't selected a transport yet,      // let's do it now.      if ((session->state() != Session::STATE_SENTREJECT) &&          (session->transport() == NULL)) {        session->ChooseTransport(stanza);      }    }    return;  }  SendErrorMessage(stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",                  "unknown session", NULL);}void SessionManager::OnIncomingResponse(const buzz::XmlElement* orig_stanza,    const buzz::XmlElement* response_stanza) {  // We don't do anything with the response now.  If we need to we can forward  // it to the session.  return;}void SessionManager::OnFailedSend(const buzz::XmlElement* orig_stanza,                                   const buzz::XmlElement* error_stanza) {  Session* session = FindSessionForStanza(orig_stanza, false);  if (session) {    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);  }}std::string SessionManager::FindClient(const buzz::XmlElement* session) {  for (const buzz::XmlElement* elem = session->FirstElement();       elem != NULL;       elem = elem->NextElement()) {    if (elem->Name().LocalPart() == "description") {      ClientMap::iterator iter = client_map_.find(elem->Name().Namespace());      if (iter != client_map_.end())        return iter->first;    }  }  return "";}void SessionManager::SendErrorMessage(const buzz::XmlElement* stanza,                                      const buzz::QName& name,                                      const std::string& type,                                      const std::string& text,                                      const buzz::XmlElement* extra_info) {  scoped_ptr<buzz::XmlElement> msg(      CreateErrorMessage(stanza, name, type, text, extra_info));  SignalOutgoingMessage(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");  for (const buzz::XmlElement* elem = stanza->FirstElement();       elem != NULL;       elem = elem->NextElement()) {    iq->AddElement(new buzz::XmlElement(*elem));  }  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(stanza);}void SessionManager::OnErrorMessage(Session* 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -