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 |