1 /* 2 * Copyright 2010 The WebRTC Project Authors. All rights reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/libjingle/xmpp/jingleinfotask.h" 12 13 #include "webrtc/libjingle/xmpp/constants.h" 14 #include "webrtc/libjingle/xmpp/xmppclient.h" 15 #include "webrtc/libjingle/xmpp/xmpptask.h" 16 #include "webrtc/base/socketaddress.h" 17 18 namespace buzz { 19 20 class JingleInfoTask::JingleInfoGetTask : public XmppTask { 21 public: 22 explicit JingleInfoGetTask(XmppTaskParentInterface* parent) 23 : XmppTask(parent, XmppEngine::HL_SINGLE), 24 done_(false) {} 25 26 virtual int ProcessStart() { 27 rtc::scoped_ptr<XmlElement> get( 28 MakeIq(STR_GET, Jid(), task_id())); 29 get->AddElement(new XmlElement(QN_JINGLE_INFO_QUERY, true)); 30 if (SendStanza(get.get()) != XMPP_RETURN_OK) { 31 return STATE_ERROR; 32 } 33 return STATE_RESPONSE; 34 } 35 virtual int ProcessResponse() { 36 if (done_) 37 return STATE_DONE; 38 return STATE_BLOCKED; 39 } 40 41 protected: 42 virtual bool HandleStanza(const XmlElement * stanza) { 43 if (!MatchResponseIq(stanza, Jid(), task_id())) 44 return false; 45 46 if (stanza->Attr(QN_TYPE) != STR_RESULT) 47 return false; 48 49 // Queue the stanza with the parent so these don't get handled out of order 50 JingleInfoTask* parent = static_cast<JingleInfoTask*>(GetParent()); 51 parent->QueueStanza(stanza); 52 53 // Wake ourselves so we can go into the done state 54 done_ = true; 55 Wake(); 56 return true; 57 } 58 59 bool done_; 60 }; 61 62 63 void JingleInfoTask::RefreshJingleInfoNow() { 64 JingleInfoGetTask* get_task = new JingleInfoGetTask(this); 65 get_task->Start(); 66 } 67 68 bool 69 JingleInfoTask::HandleStanza(const XmlElement * stanza) { 70 if (!MatchRequestIq(stanza, "set", QN_JINGLE_INFO_QUERY)) 71 return false; 72 73 // only respect relay push from the server 74 Jid from(stanza->Attr(QN_FROM)); 75 if (!from.IsEmpty() && 76 !from.BareEquals(GetClient()->jid()) && 77 from != Jid(GetClient()->jid().domain())) 78 return false; 79 80 QueueStanza(stanza); 81 return true; 82 } 83 84 int 85 JingleInfoTask::ProcessStart() { 86 std::vector<std::string> relay_hosts; 87 std::vector<rtc::SocketAddress> stun_hosts; 88 std::string relay_token; 89 const XmlElement * stanza = NextStanza(); 90 if (stanza == NULL) 91 return STATE_BLOCKED; 92 const XmlElement * query = stanza->FirstNamed(QN_JINGLE_INFO_QUERY); 93 if (query == NULL) 94 return STATE_START; 95 const XmlElement *stun = query->FirstNamed(QN_JINGLE_INFO_STUN); 96 if (stun) { 97 for (const XmlElement *server = stun->FirstNamed(QN_JINGLE_INFO_SERVER); 98 server != NULL; server = server->NextNamed(QN_JINGLE_INFO_SERVER)) { 99 std::string host = server->Attr(QN_JINGLE_INFO_HOST); 100 std::string port = server->Attr(QN_JINGLE_INFO_UDP); 101 if (host != STR_EMPTY && host != STR_EMPTY) { 102 stun_hosts.push_back(rtc::SocketAddress(host, atoi(port.c_str()))); 103 } 104 } 105 } 106 107 const XmlElement *relay = query->FirstNamed(QN_JINGLE_INFO_RELAY); 108 if (relay) { 109 relay_token = relay->TextNamed(QN_JINGLE_INFO_TOKEN); 110 for (const XmlElement *server = relay->FirstNamed(QN_JINGLE_INFO_SERVER); 111 server != NULL; server = server->NextNamed(QN_JINGLE_INFO_SERVER)) { 112 std::string host = server->Attr(QN_JINGLE_INFO_HOST); 113 if (host != STR_EMPTY) { 114 relay_hosts.push_back(host); 115 } 116 } 117 } 118 SignalJingleInfo(relay_token, relay_hosts, stun_hosts); 119 return STATE_START; 120 } 121 } 122