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:
JingleInfoGetTask(XmppTaskParentInterface * parent)22 explicit JingleInfoGetTask(XmppTaskParentInterface* parent)
23 : XmppTask(parent, XmppEngine::HL_SINGLE),
24 done_(false) {}
25
ProcessStart()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 }
ProcessResponse()35 virtual int ProcessResponse() {
36 if (done_)
37 return STATE_DONE;
38 return STATE_BLOCKED;
39 }
40
41 protected:
HandleStanza(const XmlElement * stanza)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
RefreshJingleInfoNow()63 void JingleInfoTask::RefreshJingleInfoNow() {
64 JingleInfoGetTask* get_task = new JingleInfoGetTask(this);
65 get_task->Start();
66 }
67
68 bool
HandleStanza(const XmlElement * stanza)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
ProcessStart()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