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

📄 session.cc

📁 本人收集整理的一份c/c++跨平台网络库
💻 CC
📖 第 1 页 / 共 3 页
字号:
    error_type = error->Attr(buzz::QN_TYPE);    LOG(LERROR) << "Session error:\n" << error->Str() << "\n"                << "in response to:\n" << orig_session->Str();  }  bool fatal_error = false;  ASSERT(orig_session->HasAttr(buzz::QN_TYPE));  if ((orig_session->Attr(buzz::QN_TYPE) == "transport-info")      || (orig_session->Attr(buzz::QN_TYPE) == "candidates")) {    // 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.    for (const buzz::XmlElement* elem = error->FirstElement();         NULL != elem; elem = elem->NextElement()) {      if (Transport* transport = GetTransport(elem->Name().Namespace())) {        if (!transport->OnTransportError(orig_session, elem)) {          fatal_error = true;          break;        }      }    }  } 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.    fatal_error = true;  }  if (fatal_error) {    SetError(ERROR_RESPONSE);  }}bool Session::OnInitiateMessage(const buzz::XmlElement* stanza,                                const buzz::XmlElement* session) {  if (!CheckState(stanza, STATE_INIT))    return false;  if (!FindRemoteSessionDescription(stanza, session))    return false;  initiator_ = false;  remote_name_ = stanza->Attr(buzz::QN_FROM);  SetState(STATE_RECEIVEDINITIATE);  return true;}bool Session::OnAcceptMessage(const buzz::XmlElement* stanza,                              const buzz::XmlElement* session) {  if (!CheckState(stanza, STATE_SENTINITIATE))    return false;  if (!FindRemoteSessionDescription(stanza, session))    return false;  SetState(STATE_RECEIVEDACCEPT);  return true;}bool Session::OnRejectMessage(const buzz::XmlElement* stanza,                              const buzz::XmlElement* session) {  if (!CheckState(stanza, STATE_SENTINITIATE))    return false;  SetState(STATE_RECEIVEDREJECT);  return true;}bool Session::OnRedirectMessage(const buzz::XmlElement* stanza,                                const buzz::XmlElement* session) {  if (!CheckState(stanza, STATE_SENTINITIATE))    return false;  const buzz::XmlElement *redirect_target;  if (!FindRequiredElement(stanza, session, QN_REDIRECT_TARGET,                           &redirect_target))    return false;  if (!FindRequiredAttribute(stanza, redirect_target, buzz::QN_NAME,                             &remote_name_))    return false;  const buzz::XmlElement* redirect_cookie =      session->FirstNamed(QN_REDIRECT_COOKIE);  XmlElements elems;  elems.push_back(client_->TranslateSessionDescription(description_));  if (redirect_cookie)    elems.push_back(new buzz::XmlElement(*redirect_cookie));   SendSessionMessage("initiate", elems);  // Clear the connection timeout (if any).  We will start the connection  // timer from scratch when SignalConnecting fires.  session_manager_->signaling_thread()->Clear(this, MSG_TIMEOUT);  // Reset all of the sockets back into the initial state.  for (TransportList::iterator iter = potential_transports_.begin();       iter != potential_transports_.end();       ++iter) {    (*iter)->ResetChannels();  }  ConnectDefaultTransportChannels(false);  return true;}bool Session::OnInfoMessage(const buzz::XmlElement* stanza,                            const buzz::XmlElement* session) {  XmlElements elems;  for (const buzz::XmlElement* elem = session->FirstElement();       elem != NULL;       elem = elem->NextElement()) {    elems.push_back(new buzz::XmlElement(*elem));  }  SignalInfoMessage(this, elems);  return true;}bool Session::OnTransportAcceptMessage(const buzz::XmlElement* stanza,                                       const buzz::XmlElement* session) {  if (!CheckState(stanza, STATE_SENTINITIATE))    return false;  Transport* transport = NULL;  const buzz::XmlElement* transport_elem = NULL;  for(const buzz::XmlElement* elem = session->FirstElement();      elem != NULL;      elem = elem->NextElement()) {    if (elem->Name().LocalPart() == "transport") {      Transport* transport = GetTransport(elem->Name().Namespace());      if (transport) {        if (transport_elem) {  // trying to accept two transport?          SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST,                              "modify", "transport-accept has two answers",                             NULL);          return false;        }        transport_elem = elem;        if (!transport->OnTransportAnswer(transport_elem)) {          SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST,                             "modify", "transport-accept is not acceptable",                             NULL);          return false;        }        SetTransport(transport);      }    }  }  if (!transport_elem) {    SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ALLOWED, "modify",                       "no supported transport in answer", NULL);    return false;  }  // If we discovered that we need compatibility mode and we have sent some  // candidates already (using transport-info), then we need to re-send them  // using the candidates message.  if (compatibility_mode_ && (candidates_.size() > 0)) {    ASSERT(transport_ != NULL);    ASSERT(transport_->name() == kNsP2pTransport);    OnTransportSendMessage(transport_, candidates_);  } else {    for (size_t i = 0; i < candidates_.size(); ++i)      delete candidates_[i];  }  candidates_.clear();  return true;}bool Session::OnTransportInfoMessage(const buzz::XmlElement* stanza,                                     const buzz::XmlElement* session) {  for(const buzz::XmlElement* elem = session->FirstElement();      elem != NULL;      elem = elem->NextElement()) {    if (elem->Name().LocalPart() == "transport") {      Transport* transport = GetTransport(elem->Name().Namespace());      if (transport) {        if (!transport->OnTransportMessage(elem, stanza))          return false;      }    }  }  return true;}bool Session::OnTerminateMessage(const buzz::XmlElement* stanza,                                 const buzz::XmlElement* session) {  for (const buzz::XmlElement *elem = session->FirstElement();       elem != NULL;       elem = elem->NextElement()) {    // elem->Name().LocalPart() is the reason for termination    SignalReceivedTerminateReason(this, elem->Name().LocalPart());    // elem->FirstElement() might contain a debug string for termination    const buzz::XmlElement *debugElement = elem->FirstElement();    if (debugElement != NULL) {      LOG(LS_VERBOSE) << "Received error on call: "        << debugElement->Name().LocalPart();    }  }  SetState(STATE_RECEIVEDTERMINATE);  return true;}bool Session::OnCandidatesMessage(const buzz::XmlElement* stanza,                                  const buzz::XmlElement* session) {  // If we don't have a transport, then this is the first candidates message.  // We first create a fake transport-accept message in order to finish the  // negotiation and create a transport.  if (!transport_) {    compatibility_mode_ = true;    scoped_ptr<buzz::XmlElement> transport_accept(        new buzz::XmlElement(QN_SESSION));    transport_accept->SetAttr(buzz::QN_TYPE, "transport-accept");    buzz::XmlElement* transport_offer =        new buzz::XmlElement(kQnP2pTransport, true);    transport_accept->AddElement(transport_offer);    // It is okay to pass the original stanza here.  That is only used if we    // send an error message.  Normal processing looks only at transport_accept.    bool valid = OnTransportAcceptMessage(stanza, transport_accept.get());    ASSERT(valid);  }  ASSERT(transport_ != NULL);  ASSERT(transport_->name() == kNsP2pTransport);  // Wrap the candidates in a transport element as they would appear in a  // transport-info message and send this to the transport.  scoped_ptr<buzz::XmlElement> transport_info(      new buzz::XmlElement(kQnP2pTransport, true));  for (const buzz::XmlElement* elem = session->FirstNamed(kQnLegacyCandidate);       elem != NULL;       elem = elem->NextNamed(kQnLegacyCandidate)) {    buzz::XmlElement* new_candidate = new buzz::XmlElement(*elem);    new_candidate->SetName(kQnP2pCandidate);    transport_info->AddElement(new_candidate);  }  return transport_->OnTransportMessage(transport_info.get(), stanza);}bool Session::CheckState(const buzz::XmlElement* stanza, State state) {  ASSERT(state_ == state);  if (state_ != state) {    SignalErrorMessage(this, stanza, buzz::QN_STANZA_NOT_ALLOWED, "modify",                       "message not allowed in current state", NULL);    return false;  }  return true;}bool Session::FindRequiredElement(const buzz::XmlElement* stanza,                                  const buzz::XmlElement* parent,                                  const buzz::QName& name,                                  const buzz::XmlElement** elem) {  *elem = parent->FirstNamed(name);  if (*elem == NULL) {    std::string text;    text += "element '" + parent->Name().Merged() +            "' missing required child '" + name.Merged() + "'";    SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",                       text, NULL);    return false;  }  return true;}bool Session::FindRemoteSessionDescription(const buzz::XmlElement* stanza,                                           const buzz::XmlElement* session) {  buzz::QName qn_session(session_type_, "description");  const buzz::XmlElement* desc;  if (!FindRequiredElement(stanza, session, qn_session, &desc))    return false;  remote_description_ = client_->CreateSessionDescription(desc);  return true;}bool Session::FindRequiredAttribute(const buzz::XmlElement* stanza,                                    const buzz::XmlElement* elem,                                    const buzz::QName& name,                                    std::string* value) {  if (!elem->HasAttr(name)) {    std::string text;    text += "element '" + elem->Name().Merged() +            "' missing required attribute '" + name.Merged() + "'";    SignalErrorMessage(this, stanza, buzz::QN_STANZA_BAD_REQUEST, "modify",                       text, NULL);    return false;  } else {    *value = elem->Attr(name);    return true;  }}void Session::OnMessage(talk_base::Message *pmsg) {  switch(pmsg->message_id) {  case MSG_TIMEOUT:    // Session timeout has occured.    SetError(ERROR_TIME);    break;  case MSG_ERROR:    // Any of the defined errors is most likely fatal.    Terminate();    break;  case MSG_STATE:    switch (state_) {    case STATE_SENTACCEPT:    case STATE_RECEIVEDACCEPT:      SetState(STATE_INPROGRESS);      ASSERT(transport_ != NULL);      break;    case STATE_SENTREJECT:    case STATE_SENTREDIRECT:    case STATE_RECEIVEDREJECT:      Terminate();      break;    case STATE_SENTTERMINATE:    case STATE_RECEIVEDTERMINATE:      session_manager_->DestroySession(this);      break;    default:      // Explicitly ignoring some states here.      break;    }    break;  }}} // namespace cricket

⌨️ 快捷键说明

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