Index: remoting/jingle_glue/jingle_info_request.cc |
diff --git a/remoting/jingle_glue/jingle_info_request.cc b/remoting/jingle_glue/jingle_info_request.cc |
index b8866b5bc46976f604acfc8fe6a10a9c0b266219..37437299c3ea889dc09990d11368c1bdb58793df 100644 |
--- a/remoting/jingle_glue/jingle_info_request.cc |
+++ b/remoting/jingle_glue/jingle_info_request.cc |
@@ -5,7 +5,11 @@ |
#include "remoting/jingle_glue/jingle_info_request.h" |
#include "base/task.h" |
+#include "base/message_loop.h" |
+#include "base/stl_util.h" |
#include "base/string_number_conversions.h" |
+#include "net/base/net_util.h" |
+#include "remoting/jingle_glue/host_address_resolver.h" |
#include "remoting/jingle_glue/iq_request.h" |
#include "third_party/libjingle/source/talk/base/socketaddress.h" |
#include "third_party/libjingle/source/talk/xmllite/xmlelement.h" |
@@ -13,12 +17,31 @@ |
namespace remoting { |
-JingleInfoRequest::JingleInfoRequest(IqRequest* request) |
- : request_(request) { |
+struct JingleInfoRequest::PendingDnsRequest { |
Wez
2011/08/08 23:07:59
If you made the HostAddressResolver interface more
Sergey Ulanov
2011/08/09 01:42:16
Done.
|
+ PendingDnsRequest(HostAddressRequest* request_value, int port_value) |
+ : request(request_value), |
+ port(port_value) { |
+ } |
+ |
+ scoped_ptr<HostAddressRequest> request; |
+ int port; |
+ |
+ private: |
+ DISALLOW_COPY_AND_ASSIGN(PendingDnsRequest); |
+}; |
+ |
+JingleInfoRequest::JingleInfoRequest(IqRequest* request, |
+ HostAddressResolver* host_resolver) |
+ : host_resolver_(host_resolver), |
+ request_(request) { |
request_->set_callback(NewCallback(this, &JingleInfoRequest::OnResponse)); |
} |
JingleInfoRequest::~JingleInfoRequest() { |
+ STLDeleteContainerPairSecondPointers(stun_dns_requests_.begin(), |
+ stun_dns_requests_.end()); |
+ STLDeleteContainerPointers(relay_dns_requests_.begin(), |
+ relay_dns_requests_.end()); |
} |
void JingleInfoRequest::Send(const OnJingleInfoCallback& callback) { |
@@ -28,10 +51,6 @@ void JingleInfoRequest::Send(const OnJingleInfoCallback& callback) { |
} |
void JingleInfoRequest::OnResponse(const buzz::XmlElement* stanza) { |
- std::vector<std::string> relay_hosts; |
- std::vector<talk_base::SocketAddress> stun_hosts; |
- std::string relay_token; |
- |
const buzz::XmlElement* query = |
stanza->FirstNamed(buzz::QN_JINGLE_INFO_QUERY); |
if (query == NULL) { |
@@ -53,7 +72,17 @@ void JingleInfoRequest::OnResponse(const buzz::XmlElement* stanza) { |
if (!base::StringToInt(port_str, &port)) { |
LOG(WARNING) << "Unable to parse port in stanza" << stanza->Str(); |
} else { |
- stun_hosts.push_back(talk_base::SocketAddress(host, port)); |
+ net::IPAddressNumber ip_number; |
+ if (host_resolver_ == NULL || |
+ net::ParseIPLiteralToNumber(host, &ip_number)) { |
+ stun_hosts_.push_back(talk_base::SocketAddress(host, port)); |
Wez
2011/08/08 23:07:59
It might be simpler to mandate that HostAddressReq
Sergey Ulanov
2011/08/09 01:42:16
Done.
|
+ } else { |
+ HostAddressRequest* request = host_resolver_->CreateRequest(); |
+ stun_dns_requests_[request] = new PendingDnsRequest(request, port); |
+ request->SignalDone.connect( |
+ this, &JingleInfoRequest::OnStunAddressResponse); |
+ request->Request(host); |
+ } |
} |
} |
} |
@@ -61,19 +90,63 @@ void JingleInfoRequest::OnResponse(const buzz::XmlElement* stanza) { |
const buzz::XmlElement* relay = query->FirstNamed(buzz::QN_JINGLE_INFO_RELAY); |
if (relay) { |
- relay_token = relay->TextNamed(buzz::QN_JINGLE_INFO_TOKEN); |
+ relay_token_ = relay->TextNamed(buzz::QN_JINGLE_INFO_TOKEN); |
for (const buzz::XmlElement* server = |
relay->FirstNamed(buzz::QN_JINGLE_INFO_SERVER); |
server != NULL; |
server = server->NextNamed(buzz::QN_JINGLE_INFO_SERVER)) { |
std::string host = server->Attr(buzz::QN_JINGLE_INFO_HOST); |
if (host != buzz::STR_EMPTY) { |
- relay_hosts.push_back(host); |
+ net::IPAddressNumber ip_number; |
+ if (host_resolver_ == NULL || |
+ net::ParseIPLiteralToNumber(host, &ip_number)) { |
+ relay_hosts_.push_back(host); |
Wez
2011/08/08 23:07:59
Same here.
Sergey Ulanov
2011/08/09 01:42:16
Actually we don't need to resolve relay hosts.
|
+ } else { |
+ HostAddressRequest* request = host_resolver_->CreateRequest(); |
+ relay_dns_requests_.insert(request); |
+ request->SignalDone.connect( |
+ this, &JingleInfoRequest::OnRelayAddressResponse); |
+ request->Request(host); |
+ } |
} |
} |
} |
- on_jingle_info_cb_.Run(relay_token, relay_hosts, stun_hosts); |
+ VerifyAllAddressesResolved(); |
+} |
+ |
+void JingleInfoRequest::OnStunAddressResponse( |
+ HostAddressRequest* request, |
+ const talk_base::SocketAddress& address) { |
+ RequestsMap::iterator it = stun_dns_requests_.find(request); |
+ DCHECK(it != stun_dns_requests_.end()); |
+ |
+ if (!address.IsNil()) { |
+ stun_hosts_.push_back(talk_base::SocketAddress( |
+ address.ip(), it->second->port)); |
+ } |
+ |
+ MessageLoop::current()->DeleteSoon(FROM_HERE, it->second); |
+ stun_dns_requests_.erase(it); |
+ |
+ VerifyAllAddressesResolved(); |
+} |
+ |
+void JingleInfoRequest::OnRelayAddressResponse( |
+ HostAddressRequest* request, |
+ const talk_base::SocketAddress& address) { |
+ if (!address.IsNil()) |
+ relay_hosts_.push_back(address.IPAsString()); |
+ |
+ MessageLoop::current()->DeleteSoon(FROM_HERE, request); |
+ relay_dns_requests_.erase(request); |
+ |
+ VerifyAllAddressesResolved(); |
+} |
+ |
+void JingleInfoRequest::VerifyAllAddressesResolved() { |
+ if (stun_dns_requests_.empty() && relay_dns_requests_.empty()) |
+ on_jingle_info_cb_.Run(relay_token_, relay_hosts_, stun_hosts_); |
} |
} // namespace remoting |