| Index: remoting/protocol/jingle_messages.cc
|
| diff --git a/remoting/protocol/jingle_messages.cc b/remoting/protocol/jingle_messages.cc
|
| index bc8846a0e3833bef62fa6f3fd8ec1b554d4f1577..57f9968e4ad3392e7a5df5445c94e5c2ddad4471 100644
|
| --- a/remoting/protocol/jingle_messages.cc
|
| +++ b/remoting/protocol/jingle_messages.cc
|
| @@ -33,6 +33,11 @@ const char kXmlNamespace[] = "http://www.w3.org/XML/1998/namespace";
|
| const int kPortMin = 1000;
|
| const int kPortMax = 65535;
|
|
|
| +const NameMapElement<SignalingAddress::Channel> kChannelTypes[] = {
|
| + {SignalingAddress::Channel::LCS, "lcs"},
|
| + {SignalingAddress::Channel::XMPP, "xmpp"},
|
| +};
|
| +
|
| const NameMapElement<JingleMessage::ActionType> kActionTypes[] = {
|
| { JingleMessage::SESSION_INITIATE, "session-initiate" },
|
| { JingleMessage::SESSION_ACCEPT, "session-accept" },
|
| @@ -143,6 +148,73 @@ XmlElement* FormatIceCandidate(
|
| return result;
|
| }
|
|
|
| +// Represents the XML attrbute names for the various address fields in the
|
| +// iq stanza.
|
| +enum class Field { JID, CHANNEL, ENDPOINT_ID };
|
| +
|
| +buzz::QName GetQNameByField(Field attr, bool from) {
|
| + std::string attribute_name;
|
| + switch (attr) {
|
| + case Field::JID:
|
| + attribute_name = (from) ? "from" : "to";
|
| + break;
|
| + case Field::ENDPOINT_ID:
|
| + attribute_name = (from) ? "from-endpoint-id" : "to-endpoint-id";
|
| + break;
|
| + case Field::CHANNEL:
|
| + attribute_name = (from) ? "from-channel" : "to-channel";
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + }
|
| + return QName(kEmptyNamespace, attribute_name);
|
| +}
|
| +
|
| +SignalingAddress ParseAddress(
|
| + const buzz::XmlElement* stanza, bool from, std::string* error) {
|
| + SignalingAddress empty_instance;
|
| +
|
| + std::string jid(stanza->Attr(GetQNameByField(Field::JID, from)));
|
| + std::string endpoint_id(
|
| + stanza->Attr(GetQNameByField(Field::ENDPOINT_ID, from)));
|
| + std::string channel_str(stanza->Attr(GetQNameByField(Field::CHANNEL, from)));
|
| + SignalingAddress::Channel channel;
|
| +
|
| + if (channel_str.empty()) {
|
| + channel = SignalingAddress::Channel::XMPP;
|
| + } else if (!NameToValue(kChannelTypes, channel_str, &channel)) {
|
| + *error = "Unknown channel: " + channel_str;
|
| + return empty_instance;
|
| + }
|
| +
|
| + bool isLcs = (channel == SignalingAddress::Channel::LCS);
|
| +
|
| + if (isLcs == endpoint_id.empty()) {
|
| + *error = (isLcs ? "Missing |endpoint-id| for LCS channel"
|
| + : "|endpoint_id| should be empty for XMPP channel");
|
| + return empty_instance;
|
| + }
|
| +
|
| + return SignalingAddress(jid, endpoint_id, channel);
|
| +}
|
| +
|
| +void SetAddress(buzz::XmlElement* iqElement,
|
| + const SignalingAddress& address,
|
| + bool from) {
|
| + if (address.empty()) {
|
| + return;
|
| + }
|
| +
|
| + iqElement->AddAttr(GetQNameByField(Field::JID, from), address.jid);
|
| +
|
| + if (address.channel == SignalingAddress::Channel::LCS) {
|
| + iqElement->AddAttr(GetQNameByField(Field::ENDPOINT_ID, from),
|
| + address.endpoint_id);
|
| + const char* channel_str = ValueToName(kChannelTypes, address.channel);
|
| + iqElement->AddAttr(GetQNameByField(Field::CHANNEL, from), channel_str);
|
| + }
|
| +}
|
| +
|
| } // namespace
|
|
|
| IceTransportInfo::NamedCandidate::NamedCandidate(
|
| @@ -158,6 +230,26 @@ IceTransportInfo::IceCredentials::IceCredentials(std::string channel,
|
| : channel(channel), ufrag(ufrag), password(password) {
|
| }
|
|
|
| +SignalingAddress::SignalingAddress()
|
| + : channel(SignalingAddress::Channel::XMPP) {}
|
| +
|
| +SignalingAddress::SignalingAddress(const std::string& jid)
|
| + : jid(jid), channel(SignalingAddress::Channel::XMPP) {}
|
| +
|
| +SignalingAddress::SignalingAddress(const std::string& jid,
|
| + const std::string& endpoint_id,
|
| + Channel channel)
|
| + : jid(jid), endpoint_id(endpoint_id), channel(channel) {}
|
| +
|
| +bool SignalingAddress::operator==(const SignalingAddress& other) {
|
| + return (other.endpoint_id == endpoint_id) && (other.jid == jid) &&
|
| + (other.channel == channel);
|
| +}
|
| +
|
| +bool SignalingAddress::operator!=(const SignalingAddress& other) {
|
| + return !(*this == other);
|
| +}
|
| +
|
| // static
|
| bool JingleMessage::IsJingleMessage(const buzz::XmlElement* stanza) {
|
| return stanza->Name() == QName(kJabberNamespace, "iq") &&
|
| @@ -172,7 +264,7 @@ std::string JingleMessage::GetActionName(ActionType action) {
|
|
|
| JingleMessage::JingleMessage() {}
|
|
|
| -JingleMessage::JingleMessage(const std::string& to,
|
| +JingleMessage::JingleMessage(const SignalingAddress& to,
|
| ActionType action,
|
| const std::string& sid)
|
| : to(to), action(action), sid(sid) {}
|
| @@ -193,8 +285,16 @@ bool JingleMessage::ParseXml(const buzz::XmlElement* stanza,
|
| return false;
|
| }
|
|
|
| - from = stanza->Attr(QName(kEmptyNamespace, "from"));
|
| - to = stanza->Attr(QName(kEmptyNamespace, "to"));
|
| + from = ParseAddress(stanza, true, error);
|
| + if (!error->empty()) {
|
| + return false;
|
| + }
|
| +
|
| + to = ParseAddress(stanza, false, error);
|
| + if (!error->empty()) {
|
| + return false;
|
| + }
|
| +
|
| initiator = jingle_tag->Attr(QName(kEmptyNamespace, "initiator"));
|
|
|
| std::string action_str = jingle_tag->Attr(QName(kEmptyNamespace, "action"));
|
| @@ -290,9 +390,8 @@ std::unique_ptr<buzz::XmlElement> JingleMessage::ToXml() const {
|
| new XmlElement(QName("jabber:client", "iq"), true));
|
|
|
| DCHECK(!to.empty());
|
| - root->AddAttr(QName(kEmptyNamespace, "to"), to);
|
| - if (!from.empty())
|
| - root->AddAttr(QName(kEmptyNamespace, "from"), from);
|
| + SetAddress(root.get(), to, false);
|
| + SetAddress(root.get(), from, true);
|
| root->SetAttr(QName(kEmptyNamespace, "type"), "set");
|
|
|
| XmlElement* jingle_tag =
|
| @@ -371,8 +470,13 @@ std::unique_ptr<buzz::XmlElement> JingleMessageReply::ToXml(
|
| const buzz::XmlElement* request_stanza) const {
|
| std::unique_ptr<XmlElement> iq(
|
| new XmlElement(QName(kJabberNamespace, "iq"), true));
|
| - iq->SetAttr(QName(kEmptyNamespace, "to"),
|
| - request_stanza->Attr(QName(kEmptyNamespace, "from")));
|
| +
|
| + SignalingAddress original_from;
|
| + std::string error_message;
|
| + original_from = ParseAddress(request_stanza, true, &error_message);
|
| + DCHECK(error_message.empty());
|
| + SetAddress(iq.get(), original_from, false);
|
| +
|
| iq->SetAttr(QName(kEmptyNamespace, "id"),
|
| request_stanza->Attr(QName(kEmptyNamespace, "id")));
|
|
|
|
|