| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "remoting/protocol/jingle_messages.h" | 5 #include "remoting/protocol/jingle_messages.h" |
| 6 | 6 |
| 7 #include "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/strings/string_number_conversions.h" | 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "remoting/base/constants.h" | 9 #include "remoting/base/constants.h" |
| 10 #include "remoting/protocol/content_description.h" | 10 #include "remoting/protocol/content_description.h" |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 335 *error = "Unknown action " + action_str; | 335 *error = "Unknown action " + action_str; |
| 336 return false; | 336 return false; |
| 337 } | 337 } |
| 338 | 338 |
| 339 sid = jingle_tag->Attr(QName(kEmptyNamespace, "sid")); | 339 sid = jingle_tag->Attr(QName(kEmptyNamespace, "sid")); |
| 340 if (sid.empty()) { | 340 if (sid.empty()) { |
| 341 *error = "sid attribute is missing"; | 341 *error = "sid attribute is missing"; |
| 342 return false; | 342 return false; |
| 343 } | 343 } |
| 344 | 344 |
| 345 const XmlElement* attachments_tag = |
| 346 jingle_tag->FirstNamed(QName(kChromotingXmlNamespace, "attachments")); |
| 347 if (attachments_tag) { |
| 348 attachments.reset(new XmlElement(*attachments_tag)); |
| 349 } else { |
| 350 attachments.reset(); |
| 351 } |
| 352 |
| 345 if (action == SESSION_INFO) { | 353 if (action == SESSION_INFO) { |
| 346 // session-info messages may contain arbitrary information not | 354 // session-info messages may contain arbitrary information not |
| 347 // defined by the Jingle protocol. We don't need to parse it. | 355 // defined by the Jingle protocol. We don't need to parse it. |
| 348 const XmlElement* child = jingle_tag->FirstElement(); | 356 const XmlElement* child = jingle_tag->FirstElement(); |
| 357 // Plugin messages are action independent, which should not be considered as |
| 358 // session-info. |
| 359 if (child == attachments_tag) { |
| 360 child = child->NextElement(); |
| 361 } |
| 349 if (child) { | 362 if (child) { |
| 350 // session-info is allowed to be empty. | 363 // session-info is allowed to be empty. |
| 351 info.reset(new XmlElement(*child)); | 364 info.reset(new XmlElement(*child)); |
| 352 } else { | 365 } else { |
| 353 info.reset(nullptr); | 366 info.reset(); |
| 354 } | 367 } |
| 355 return true; | 368 return true; |
| 356 } | 369 } |
| 357 | 370 |
| 358 const XmlElement* reason_tag = | 371 const XmlElement* reason_tag = |
| 359 jingle_tag->FirstNamed(QName(kJingleNamespace, "reason")); | 372 jingle_tag->FirstNamed(QName(kJingleNamespace, "reason")); |
| 360 if (reason_tag && reason_tag->FirstElement()) { | 373 if (reason_tag && reason_tag->FirstElement()) { |
| 361 if (!NameToValue(kReasons, reason_tag->FirstElement()->Name().LocalPart(), | 374 if (!NameToValue(kReasons, reason_tag->FirstElement()->Name().LocalPart(), |
| 362 &reason)) { | 375 &reason)) { |
| 363 reason = UNKNOWN_REASON; | 376 reason = UNKNOWN_REASON; |
| 364 } | 377 } |
| 365 } | 378 } |
| 366 | 379 |
| 367 const XmlElement* error_code_tag = | 380 const XmlElement* error_code_tag = |
| 368 jingle_tag->FirstNamed(QName(kChromotingXmlNamespace, "error-code")); | 381 jingle_tag->FirstNamed(QName(kChromotingXmlNamespace, "error-code")); |
| 369 if (error_code_tag && !error_code_tag->BodyText().empty()) { | 382 if (error_code_tag && !error_code_tag->BodyText().empty()) { |
| 370 if (!ParseErrorCode(error_code_tag->BodyText(), &error_code)) { | 383 if (!ParseErrorCode(error_code_tag->BodyText(), &error_code)) { |
| 371 LOG(WARNING) << "Unknown error-code received " | 384 LOG(WARNING) << "Unknown error-code received " |
| 372 << error_code_tag->BodyText(); | 385 << error_code_tag->BodyText(); |
| 373 error_code = UNKNOWN_ERROR; | 386 error_code = UNKNOWN_ERROR; |
| 374 } | 387 } |
| 375 } | 388 } |
| 376 | 389 |
| 377 if (action == SESSION_TERMINATE) | 390 if (action == SESSION_TERMINATE) { |
| 378 return true; | 391 return true; |
| 392 } |
| 379 | 393 |
| 380 const XmlElement* content_tag = | 394 const XmlElement* content_tag = |
| 381 jingle_tag->FirstNamed(QName(kJingleNamespace, "content")); | 395 jingle_tag->FirstNamed(QName(kJingleNamespace, "content")); |
| 382 if (!content_tag) { | 396 if (!content_tag) { |
| 383 *error = "content tag is missing"; | 397 *error = "content tag is missing"; |
| 384 return false; | 398 return false; |
| 385 } | 399 } |
| 386 | 400 |
| 387 std::string content_name = content_tag->Attr(QName(kEmptyNamespace, "name")); | 401 std::string content_name = content_tag->Attr(QName(kEmptyNamespace, "name")); |
| 388 if (content_name != ContentDescription::kChromotingContentName) { | 402 if (content_name != ContentDescription::kChromotingContentName) { |
| 389 *error = "Unexpected content name: " + content_name; | 403 *error = "Unexpected content name: " + content_name; |
| 390 return false; | 404 return false; |
| 391 } | 405 } |
| 392 | 406 |
| 393 const XmlElement* webrtc_transport_tag = content_tag->FirstNamed( | 407 const XmlElement* webrtc_transport_tag = content_tag->FirstNamed( |
| 394 QName(kWebrtcTransportNamespace, "transport")); | 408 QName(kWebrtcTransportNamespace, "transport")); |
| 395 if (webrtc_transport_tag) { | 409 if (webrtc_transport_tag) { |
| 396 transport_info.reset(new buzz::XmlElement(*webrtc_transport_tag)); | 410 transport_info.reset(new buzz::XmlElement(*webrtc_transport_tag)); |
| 397 } | 411 } |
| 398 | 412 |
| 399 description.reset(nullptr); | 413 description.reset(); |
| 400 if (action == SESSION_INITIATE || action == SESSION_ACCEPT) { | 414 if (action == SESSION_INITIATE || action == SESSION_ACCEPT) { |
| 401 const XmlElement* description_tag = content_tag->FirstNamed( | 415 const XmlElement* description_tag = content_tag->FirstNamed( |
| 402 QName(kChromotingXmlNamespace, "description")); | 416 QName(kChromotingXmlNamespace, "description")); |
| 403 if (!description_tag) { | 417 if (!description_tag) { |
| 404 *error = "Missing chromoting content description"; | 418 *error = "Missing chromoting content description"; |
| 405 return false; | 419 return false; |
| 406 } | 420 } |
| 407 | 421 |
| 408 description = ContentDescription::ParseXml(description_tag, | 422 description = ContentDescription::ParseXml(description_tag, |
| 409 webrtc_transport_tag != nullptr); | 423 webrtc_transport_tag != nullptr); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 432 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); | 446 root->SetAttr(QName(kEmptyNamespace, "type"), "set"); |
| 433 | 447 |
| 434 XmlElement* jingle_tag = | 448 XmlElement* jingle_tag = |
| 435 new XmlElement(QName(kJingleNamespace, "jingle"), true); | 449 new XmlElement(QName(kJingleNamespace, "jingle"), true); |
| 436 root->AddElement(jingle_tag); | 450 root->AddElement(jingle_tag); |
| 437 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); | 451 jingle_tag->AddAttr(QName(kEmptyNamespace, "sid"), sid); |
| 438 SetAddress(root.get(), jingle_tag, to, false); | 452 SetAddress(root.get(), jingle_tag, to, false); |
| 439 SetAddress(root.get(), jingle_tag, from, true); | 453 SetAddress(root.get(), jingle_tag, from, true); |
| 440 | 454 |
| 441 const char* action_attr = ValueToName(kActionTypes, action); | 455 const char* action_attr = ValueToName(kActionTypes, action); |
| 442 if (!action_attr) | 456 if (!action_attr) { |
| 443 LOG(FATAL) << "Invalid action value " << action; | 457 LOG(FATAL) << "Invalid action value " << action; |
| 458 } |
| 444 jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr); | 459 jingle_tag->AddAttr(QName(kEmptyNamespace, "action"), action_attr); |
| 445 | 460 |
| 461 if (attachments) { |
| 462 jingle_tag->AddElement(new XmlElement(*attachments)); |
| 463 } |
| 464 |
| 446 if (action == SESSION_INFO) { | 465 if (action == SESSION_INFO) { |
| 447 if (info.get()) | 466 if (info.get()) { |
| 448 jingle_tag->AddElement(new XmlElement(*info.get())); | 467 jingle_tag->AddElement(new XmlElement(*info.get())); |
| 468 } |
| 449 return root; | 469 return root; |
| 450 } | 470 } |
| 451 | 471 |
| 452 if (action == SESSION_INITIATE) | 472 if (action == SESSION_INITIATE) { |
| 453 jingle_tag->AddAttr(QName(kEmptyNamespace, "initiator"), initiator); | 473 jingle_tag->AddAttr(QName(kEmptyNamespace, "initiator"), initiator); |
| 474 } |
| 454 | 475 |
| 455 if (reason != UNKNOWN_REASON) { | 476 if (reason != UNKNOWN_REASON) { |
| 456 XmlElement* reason_tag = new XmlElement(QName(kJingleNamespace, "reason")); | 477 XmlElement* reason_tag = new XmlElement(QName(kJingleNamespace, "reason")); |
| 457 jingle_tag->AddElement(reason_tag); | 478 jingle_tag->AddElement(reason_tag); |
| 458 reason_tag->AddElement(new XmlElement( | 479 reason_tag->AddElement(new XmlElement( |
| 459 QName(kJingleNamespace, ValueToName(kReasons, reason)))); | 480 QName(kJingleNamespace, ValueToName(kReasons, reason)))); |
| 460 | 481 |
| 461 if (error_code != UNKNOWN_ERROR) { | 482 if (error_code != UNKNOWN_ERROR) { |
| 462 XmlElement* error_code_tag = | 483 XmlElement* error_code_tag = |
| 463 new XmlElement(QName(kChromotingXmlNamespace, "error-code")); | 484 new XmlElement(QName(kChromotingXmlNamespace, "error-code")); |
| 464 jingle_tag->AddElement(error_code_tag); | 485 jingle_tag->AddElement(error_code_tag); |
| 465 error_code_tag->SetBodyText(ErrorCodeToString(error_code)); | 486 error_code_tag->SetBodyText(ErrorCodeToString(error_code)); |
| 466 } | 487 } |
| 467 } | 488 } |
| 468 | 489 |
| 469 if (action != SESSION_TERMINATE) { | 490 if (action != SESSION_TERMINATE) { |
| 470 XmlElement* content_tag = | 491 XmlElement* content_tag = |
| 471 new XmlElement(QName(kJingleNamespace, "content")); | 492 new XmlElement(QName(kJingleNamespace, "content")); |
| 472 jingle_tag->AddElement(content_tag); | 493 jingle_tag->AddElement(content_tag); |
| 473 | 494 |
| 474 content_tag->AddAttr(QName(kEmptyNamespace, "name"), | 495 content_tag->AddAttr(QName(kEmptyNamespace, "name"), |
| 475 ContentDescription::kChromotingContentName); | 496 ContentDescription::kChromotingContentName); |
| 476 content_tag->AddAttr(QName(kEmptyNamespace, "creator"), "initiator"); | 497 content_tag->AddAttr(QName(kEmptyNamespace, "creator"), "initiator"); |
| 477 | 498 |
| 478 if (description) | 499 if (description) { |
| 479 content_tag->AddElement(description->ToXml()); | 500 content_tag->AddElement(description->ToXml()); |
| 501 } |
| 480 | 502 |
| 481 if (transport_info) { | 503 if (transport_info) { |
| 482 content_tag->AddElement(new XmlElement(*transport_info)); | 504 content_tag->AddElement(new XmlElement(*transport_info)); |
| 483 } else if (description && description->config()->webrtc_supported()) { | 505 } else if (description && description->config()->webrtc_supported()) { |
| 484 content_tag->AddElement( | 506 content_tag->AddElement( |
| 485 new XmlElement(QName(kWebrtcTransportNamespace, "transport"))); | 507 new XmlElement(QName(kWebrtcTransportNamespace, "transport"))); |
| 486 } | 508 } |
| 487 } | 509 } |
| 488 | 510 |
| 489 return root; | 511 return root; |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 name = QName(kJabberNamespace, "unexpected-request"); | 588 name = QName(kJabberNamespace, "unexpected-request"); |
| 567 break; | 589 break; |
| 568 case UNSUPPORTED_INFO: | 590 case UNSUPPORTED_INFO: |
| 569 type = "modify"; | 591 type = "modify"; |
| 570 name = QName(kJabberNamespace, "feature-not-implemented"); | 592 name = QName(kJabberNamespace, "feature-not-implemented"); |
| 571 break; | 593 break; |
| 572 default: | 594 default: |
| 573 NOTREACHED(); | 595 NOTREACHED(); |
| 574 } | 596 } |
| 575 | 597 |
| 576 if (!text.empty()) | 598 if (!text.empty()) { |
| 577 error_text = text; | 599 error_text = text; |
| 600 } |
| 578 | 601 |
| 579 error->SetAttr(QName(kEmptyNamespace, "type"), type); | 602 error->SetAttr(QName(kEmptyNamespace, "type"), type); |
| 580 | 603 |
| 581 // If the error name is not in the standard namespace, we have | 604 // If the error name is not in the standard namespace, we have |
| 582 // to first add some error from that namespace. | 605 // to first add some error from that namespace. |
| 583 if (name.Namespace() != kJabberNamespace) { | 606 if (name.Namespace() != kJabberNamespace) { |
| 584 error->AddElement( | 607 error->AddElement( |
| 585 new buzz::XmlElement(QName(kJabberNamespace, "undefined-condition"))); | 608 new buzz::XmlElement(QName(kJabberNamespace, "undefined-condition"))); |
| 586 } | 609 } |
| 587 error->AddElement(new buzz::XmlElement(name)); | 610 error->AddElement(new buzz::XmlElement(name)); |
| 588 | 611 |
| 589 if (!error_text.empty()) { | 612 if (!error_text.empty()) { |
| 590 // It's okay to always use English here. This text is for | 613 // It's okay to always use English here. This text is for |
| 591 // debugging purposes only. | 614 // debugging purposes only. |
| 592 buzz::XmlElement* text_elem = | 615 buzz::XmlElement* text_elem = |
| 593 new buzz::XmlElement(QName(kJabberNamespace, "text")); | 616 new buzz::XmlElement(QName(kJabberNamespace, "text")); |
| 594 text_elem->SetAttr(QName(kXmlNamespace, "lang"), "en"); | 617 text_elem->SetAttr(QName(kXmlNamespace, "lang"), "en"); |
| 595 text_elem->SetBodyText(error_text); | 618 text_elem->SetBodyText(error_text); |
| 596 error->AddElement(text_elem); | 619 error->AddElement(text_elem); |
| 597 } | 620 } |
| 598 | 621 |
| 599 return iq; | 622 return iq; |
| 600 } | 623 } |
| 601 | 624 |
| 602 IceTransportInfo::IceTransportInfo() {} | 625 IceTransportInfo::IceTransportInfo() {} |
| 603 IceTransportInfo::~IceTransportInfo() {} | 626 IceTransportInfo::~IceTransportInfo() {} |
| 604 | 627 |
| 605 bool IceTransportInfo::ParseXml( | 628 bool IceTransportInfo::ParseXml( |
| 606 const buzz::XmlElement* element) { | 629 const buzz::XmlElement* element) { |
| 607 if (element->Name() != QName(kIceTransportNamespace, "transport")) | 630 if (element->Name() != QName(kIceTransportNamespace, "transport")) { |
| 608 return false; | 631 return false; |
| 632 } |
| 609 | 633 |
| 610 ice_credentials.clear(); | 634 ice_credentials.clear(); |
| 611 candidates.clear(); | 635 candidates.clear(); |
| 612 | 636 |
| 613 QName qn_credentials(kIceTransportNamespace, "credentials"); | 637 QName qn_credentials(kIceTransportNamespace, "credentials"); |
| 614 for (const XmlElement* credentials_tag = element->FirstNamed(qn_credentials); | 638 for (const XmlElement* credentials_tag = element->FirstNamed(qn_credentials); |
| 615 credentials_tag; | 639 credentials_tag; |
| 616 credentials_tag = credentials_tag->NextNamed(qn_credentials)) { | 640 credentials_tag = credentials_tag->NextNamed(qn_credentials)) { |
| 617 IceTransportInfo::IceCredentials credentials; | 641 IceTransportInfo::IceCredentials credentials; |
| 618 if (!ParseIceCredentials(credentials_tag, &credentials)) | 642 if (!ParseIceCredentials(credentials_tag, &credentials)) { |
| 619 return false; | 643 return false; |
| 644 } |
| 620 ice_credentials.push_back(credentials); | 645 ice_credentials.push_back(credentials); |
| 621 } | 646 } |
| 622 | 647 |
| 623 QName qn_candidate(kIceTransportNamespace, "candidate"); | 648 QName qn_candidate(kIceTransportNamespace, "candidate"); |
| 624 for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate); | 649 for (const XmlElement* candidate_tag = element->FirstNamed(qn_candidate); |
| 625 candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) { | 650 candidate_tag; candidate_tag = candidate_tag->NextNamed(qn_candidate)) { |
| 626 IceTransportInfo::NamedCandidate candidate; | 651 IceTransportInfo::NamedCandidate candidate; |
| 627 if (!ParseIceCandidate(candidate_tag, &candidate)) | 652 if (!ParseIceCandidate(candidate_tag, &candidate)) { |
| 628 return false; | 653 return false; |
| 654 } |
| 629 candidates.push_back(candidate); | 655 candidates.push_back(candidate); |
| 630 } | 656 } |
| 631 | 657 |
| 632 return true; | 658 return true; |
| 633 } | 659 } |
| 634 | 660 |
| 635 std::unique_ptr<buzz::XmlElement> IceTransportInfo::ToXml() const { | 661 std::unique_ptr<buzz::XmlElement> IceTransportInfo::ToXml() const { |
| 636 std::unique_ptr<buzz::XmlElement> result( | 662 std::unique_ptr<buzz::XmlElement> result( |
| 637 new XmlElement(QName(kIceTransportNamespace, "transport"), true)); | 663 new XmlElement(QName(kIceTransportNamespace, "transport"), true)); |
| 638 for (const IceCredentials& credentials : ice_credentials) { | 664 for (const IceCredentials& credentials : ice_credentials) { |
| 639 result->AddElement(FormatIceCredentials(credentials)); | 665 result->AddElement(FormatIceCredentials(credentials)); |
| 640 } | 666 } |
| 641 for (const NamedCandidate& candidate : candidates) { | 667 for (const NamedCandidate& candidate : candidates) { |
| 642 result->AddElement(FormatIceCandidate(candidate)); | 668 result->AddElement(FormatIceCandidate(candidate)); |
| 643 } | 669 } |
| 644 return result; | 670 return result; |
| 645 } | 671 } |
| 646 | 672 |
| 647 } // namespace protocol | 673 } // namespace protocol |
| 648 } // namespace remoting | 674 } // namespace remoting |
| OLD | NEW |