1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved.
2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be
3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file.
4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/utility/local_discovery/service_discovery_message_handler.h"
6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
7bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch#include <algorithm>
8bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
9424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "base/lazy_instance.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/common/local_discovery/local_discovery_messages.h"
115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "chrome/common/local_discovery/service_discovery_client_impl.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/utility/utility_thread.h"
13424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "net/socket/socket_descriptor.h"
14a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "net/udp/datagram_server_socket.h"
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace local_discovery {
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace {
19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ClosePlatformSocket(net::SocketDescriptor socket);
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
22a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Sets socket factory used by |net::CreatePlatformSocket|. Implemetation
23a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// keeps single socket that will be returned to the first call to
24a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// |net::CreatePlatformSocket| during object lifetime.
25a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class ScopedSocketFactory : public net::PlatformSocketFactory {
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
27a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  explicit ScopedSocketFactory(net::SocketDescriptor socket) : socket_(socket) {
28a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    net::PlatformSocketFactory::SetInstance(this);
2958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
3058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
31a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~ScopedSocketFactory() {
32a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    net::PlatformSocketFactory::SetInstance(NULL);
33a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    ClosePlatformSocket(socket_);
34a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    socket_ = net::kInvalidSocket;
35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  virtual net::SocketDescriptor CreateSocket(int family, int type,
3858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                                             int protocol) OVERRIDE {
39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK_EQ(type, SOCK_DGRAM);
40a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(family == AF_INET || family == AF_INET6);
4158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    net::SocketDescriptor result = net::kInvalidSocket;
42a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    std::swap(result, socket_);
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return result;
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
46bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
47a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::SocketDescriptor socket_;
48a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedSocketFactory);
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
51a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)struct SocketInfo {
52a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  SocketInfo(net::SocketDescriptor socket,
53a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             net::AddressFamily address_family,
54a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             uint32 interface_index)
55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      : socket(socket),
56a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        address_family(address_family),
57a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        interface_index(interface_index) {
58a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
59a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::SocketDescriptor socket;
60a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::AddressFamily address_family;
61a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  uint32 interface_index;
62a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)};
63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
64a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)// Returns list of sockets preallocated before.
65a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)class PreCreatedMDnsSocketFactory : public net::MDnsSocketFactory {
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
67a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  PreCreatedMDnsSocketFactory() {}
68a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual ~PreCreatedMDnsSocketFactory() {
69a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Not empty if process exits too fast, before starting mDns code. If
70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // happened, destructors may crash accessing destroyed global objects.
71a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    sockets_.weak_clear();
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
74a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // net::MDnsSocketFactory implementation:
75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  virtual void CreateSockets(
76a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ScopedVector<net::DatagramServerSocket>* sockets) OVERRIDE {
77a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    sockets->swap(sockets_);
78a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    Reset();
79a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
80a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
81a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  void AddSocket(const SocketInfo& socket_info) {
82a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    // Takes ownership of socket_info.socket;
83a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    ScopedSocketFactory platform_factory(socket_info.socket);
84a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    scoped_ptr<net::DatagramServerSocket> socket(
85a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        net::CreateAndBindMDnsSocket(socket_info.address_family,
86a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                     socket_info.interface_index));
87a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    if (socket) {
88a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      socket->DetachFromThread();
89a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      sockets_.push_back(socket.release());
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    }
91a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
92a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
93a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  void Reset() {
94a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    sockets_.clear();
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private:
98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ScopedVector<net::DatagramServerSocket> sockets_;
99a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
100a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(PreCreatedMDnsSocketFactory);
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::LazyInstance<PreCreatedMDnsSocketFactory>
104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    g_local_discovery_socket_factory = LAZY_INSTANCE_INITIALIZER;
105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
10658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_WIN)
10758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
10858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ClosePlatformSocket(net::SocketDescriptor socket) {
10958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ::closesocket(socket);
11058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
11158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
11258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StaticInitializeSocketFactory() {
113a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  net::InterfaceIndexFamilyList interfaces(net::GetMDnsInterfacesToBind());
114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < interfaces.size(); ++i) {
115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DCHECK(interfaces[i].second == net::ADDRESS_FAMILY_IPV4 ||
116a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           interfaces[i].second == net::ADDRESS_FAMILY_IPV6);
117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    net::SocketDescriptor descriptor =
118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        net::CreatePlatformSocket(
119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            net::ConvertAddressFamily(interfaces[i].second), SOCK_DGRAM,
120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                      IPPROTO_UDP);
121a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    g_local_discovery_socket_factory.Get().AddSocket(
122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SocketInfo(descriptor, interfaces[i].second, interfaces[i].first));
123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
12458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
12558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#else  // OS_WIN
127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
12858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ClosePlatformSocket(net::SocketDescriptor socket) {
12958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  ::close(socket);
13058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
13258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void StaticInitializeSocketFactory() {
13358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif  // OS_WIN
136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
13768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void SendHostMessageOnUtilityThread(IPC::Message* msg) {
13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  content::UtilityThread::Get()->Send(msg);
139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
14158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string WatcherUpdateToString(ServiceWatcher::UpdateType update) {
14258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  switch (update) {
14358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceWatcher::UPDATE_ADDED:
14458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "UPDATE_ADDED";
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceWatcher::UPDATE_CHANGED:
14658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "UPDATE_CHANGED";
14758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceWatcher::UPDATE_REMOVED:
14858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "UPDATE_REMOVED";
14958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceWatcher::UPDATE_INVALIDATED:
15058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "UPDATE_INVALIDATED";
15158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
15258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return "Unknown Update";
15358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
15458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
15558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string ResolverStatusToString(ServiceResolver::RequestStatus status) {
15658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  switch (status) {
15758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceResolver::STATUS_SUCCESS:
15858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "STATUS_SUCESS";
15958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceResolver::STATUS_REQUEST_TIMEOUT:
16058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "STATUS_REQUEST_TIMEOUT";
16158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ServiceResolver::STATUS_KNOWN_NONEXISTENT:
16258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return "STATUS_KNOWN_NONEXISTENT";
16358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
16458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return "Unknown Status";
16558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
16658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace
168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochServiceDiscoveryMessageHandler::ServiceDiscoveryMessageHandler() {
170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochServiceDiscoveryMessageHandler::~ServiceDiscoveryMessageHandler() {
1733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!discovery_thread_);
174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::PreSandboxStartup() {
17758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  StaticInitializeSocketFactory();
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::InitializeMdns() {
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (service_discovery_client_ || mdns_client_)
182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  mdns_client_ = net::MDnsClient::CreateDefault();
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool result =
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      mdns_client_->StartListening(g_local_discovery_socket_factory.Pointer());
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Close unused sockets.
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  g_local_discovery_socket_factory.Get().Reset();
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!result) {
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    VLOG(1) << "Failed to start MDnsClient";
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    Send(new LocalDiscoveryHostMsg_Error());
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_discovery_client_.reset(
196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new local_discovery::ServiceDiscoveryClientImpl(mdns_client_.get()));
197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
199ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ServiceDiscoveryMessageHandler::InitializeThread() {
2001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (discovery_task_runner_.get())
201ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
202ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (discovery_thread_)
203ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
204ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  utility_task_runner_ = base::MessageLoop::current()->message_loop_proxy();
205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  discovery_thread_.reset(new base::Thread("ServiceDiscoveryThread"));
206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (discovery_thread_->StartWithOptions(thread_options)) {
208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    discovery_task_runner_ = discovery_thread_->message_loop_proxy();
209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    discovery_task_runner_->PostTask(FROM_HERE,
210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        base::Bind(&ServiceDiscoveryMessageHandler::InitializeMdns,
211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    base::Unretained(this)));
212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
2131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  return discovery_task_runner_.get() != NULL;
214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ServiceDiscoveryMessageHandler::OnMessageReceived(
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const IPC::Message& message) {
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool handled = true;
219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryMessageHandler, message)
22058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_POSIX)
22158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_SetSockets, OnSetSockets)
22258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif  // OS_POSIX
223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_StartWatcher, OnStartWatcher)
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DiscoverServices, OnDiscoverServices)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_SetActivelyRefreshServices,
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                        OnSetActivelyRefreshServices)
227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DestroyWatcher, OnDestroyWatcher)
228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_ResolveService, OnResolveService)
229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DestroyResolver, OnDestroyResolver)
230bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_ResolveLocalDomain,
231bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                        OnResolveLocalDomain)
232bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DestroyLocalDomainResolver,
233bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                        OnDestroyLocalDomainResolver)
2343551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_ShutdownLocalDiscovery,
2353551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        ShutdownLocalDiscovery)
236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_UNHANDLED(handled = false)
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  IPC_END_MESSAGE_MAP()
238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return handled;
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::PostTask(
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const tracked_objects::Location& from_here,
243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::Closure& task) {
244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!InitializeThread())
245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  discovery_task_runner_->PostTask(from_here, task);
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
24958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_POSIX)
25058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void ServiceDiscoveryMessageHandler::OnSetSockets(
251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::vector<LocalDiscoveryMsg_SocketInfo>& sockets) {
252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (size_t i = 0; i < sockets.size(); ++i) {
253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    g_local_discovery_socket_factory.Get().AddSocket(
254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        SocketInfo(sockets[i].descriptor.fd, sockets[i].address_family,
255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                   sockets[i].interface_index));
256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
25758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
25858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#endif  // OS_POSIX
25958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnStartWatcher(
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_type) {
263ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
264ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::StartWatcher,
265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id, service_type));
266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDiscoverServices(uint64 id,
269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                        bool force_update) {
270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::DiscoverServices,
272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id, force_update));
273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ServiceDiscoveryMessageHandler::OnSetActivelyRefreshServices(
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint64 id, bool actively_refresh_services) {
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  PostTask(FROM_HERE,
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           base::Bind(
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               &ServiceDiscoveryMessageHandler::SetActivelyRefreshServices,
2805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               base::Unretained(this), id, actively_refresh_services));
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDestroyWatcher(uint64 id) {
284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::DestroyWatcher,
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id));
287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnResolveService(
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_name) {
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::ResolveService,
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id, service_name));
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDestroyResolver(uint64 id) {
298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::DestroyResolver,
300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id));
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
303bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::OnResolveLocalDomain(
304bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    uint64 id, const std::string& domain,
305bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    net::AddressFamily address_family) {
306bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    PostTask(FROM_HERE,
307bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::ResolveLocalDomain,
308bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                      base::Unretained(this), id, domain, address_family));
309bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
310bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
311bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDestroyLocalDomainResolver(uint64 id) {
312bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  PostTask(FROM_HERE,
313bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch           base::Bind(
314bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch               &ServiceDiscoveryMessageHandler::DestroyLocalDomainResolver,
315bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch               base::Unretained(this), id));
316bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
317bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::StartWatcher(
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
320ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_type) {
3214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "StartWatcher, id=" << id << ", type=" << service_type;
322ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
323ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(!ContainsKey(service_watchers_, id));
325ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<ServiceWatcher> watcher(
326ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      service_discovery_client_->CreateServiceWatcher(
327ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          service_type,
328ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          base::Bind(&ServiceDiscoveryMessageHandler::OnServiceUpdated,
329ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     base::Unretained(this), id)));
330ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  watcher->Start();
331ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_watchers_[id].reset(watcher.release());
332ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
333ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
334ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::DiscoverServices(uint64 id,
335ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                      bool force_update) {
3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "DiscoverServices, id=" << id;
337ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
338ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
339ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(ContainsKey(service_watchers_, id));
340ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_watchers_[id]->DiscoverNewServices(force_update);
341ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
342ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ServiceDiscoveryMessageHandler::SetActivelyRefreshServices(
3445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    uint64 id,
3455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool actively_refresh_services) {
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  VLOG(1) << "ActivelyRefreshServices, id=" << id;
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!service_discovery_client_)
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
3495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(ContainsKey(service_watchers_, id));
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  service_watchers_[id]->SetActivelyRefreshServices(actively_refresh_services);
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
353ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::DestroyWatcher(uint64 id) {
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "DestoryWatcher, id=" << id;
355ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
356ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
357ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_watchers_.erase(id);
358ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
359ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
360ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::ResolveService(
361ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
362ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_name) {
3634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "ResolveService, id=" << id << ", name=" << service_name;
364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(!ContainsKey(service_resolvers_, id));
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<ServiceResolver> resolver(
368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      service_discovery_client_->CreateServiceResolver(
369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          service_name,
370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          base::Bind(&ServiceDiscoveryMessageHandler::OnServiceResolved,
371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     base::Unretained(this), id)));
372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  resolver->StartResolving();
373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_resolvers_[id].reset(resolver.release());
374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::DestroyResolver(uint64 id) {
3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "DestroyResolver, id=" << id;
378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_resolvers_.erase(id);
381ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
382ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
383bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::ResolveLocalDomain(
384bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    uint64 id,
385bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    const std::string& domain,
386bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    net::AddressFamily address_family) {
3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "ResolveLocalDomain, id=" << id << ", domain=" << domain;
388bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (!service_discovery_client_)
389bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    return;
390bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(!ContainsKey(local_domain_resolvers_, id));
391bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<LocalDomainResolver> resolver(
392bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      service_discovery_client_->CreateLocalDomainResolver(
393bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          domain, address_family,
394bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          base::Bind(&ServiceDiscoveryMessageHandler::OnLocalDomainResolved,
395bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                     base::Unretained(this), id)));
396bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  resolver->Start();
397bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  local_domain_resolvers_[id].reset(resolver.release());
398bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
399bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
400bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::DestroyLocalDomainResolver(uint64 id) {
4014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "DestroyLocalDomainResolver, id=" << id;
402bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (!service_discovery_client_)
403bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    return;
404bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  local_domain_resolvers_.erase(id);
405bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
406bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
4073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ServiceDiscoveryMessageHandler::ShutdownLocalDiscovery() {
4081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!discovery_task_runner_.get())
4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    return;
4104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
4113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  discovery_task_runner_->PostTask(
4123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
4133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&ServiceDiscoveryMessageHandler::ShutdownOnIOThread,
4143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 base::Unretained(this)));
4153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // This will wait for message loop to drain, so ShutdownOnIOThread will
4173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // definitely be called.
4183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  discovery_thread_.reset();
4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
4213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ServiceDiscoveryMessageHandler::ShutdownOnIOThread() {
4224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "ShutdownLocalDiscovery";
4233551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  service_watchers_.clear();
4243551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  service_resolvers_.clear();
4253551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  local_domain_resolvers_.clear();
4263551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  service_discovery_client_.reset();
4273551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  mdns_client_.reset();
4283551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
4293551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
430ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnServiceUpdated(
431ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
432ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ServiceWatcher::UpdateType update,
433ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& name) {
4344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "OnServiceUpdated, id=" << id
4354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          << ", status=" << WatcherUpdateToString(update) << ", name=" << name;
436ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(service_discovery_client_);
43768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
43868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Send(new LocalDiscoveryHostMsg_WatcherCallback(id, update, name));
439ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
440ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
441ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnServiceResolved(
442ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
443ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ServiceResolver::RequestStatus status,
444ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const ServiceDescription& description) {
4454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "OnServiceResolved, id=" << id
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          << ", status=" << ResolverStatusToString(status)
4474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          << ", name=" << description.service_name;
44858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
449ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(service_discovery_client_);
45068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Send(new LocalDiscoveryHostMsg_ResolverCallback(id, status, description));
451ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
452ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
453bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::OnLocalDomainResolved(
454bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    uint64 id,
455bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    bool success,
456424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::IPAddressNumber& address_ipv4,
457424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)    const net::IPAddressNumber& address_ipv6) {
4584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  VLOG(1) << "OnLocalDomainResolved, id=" << id
4591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          << ", IPv4=" << (address_ipv4.empty() ? "" :
4601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                           net::IPAddressToString(address_ipv4))
4611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)          << ", IPv6=" << (address_ipv6.empty() ? "" :
4621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                           net::IPAddressToString(address_ipv6));
46358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
464bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(service_discovery_client_);
46568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  Send(new LocalDiscoveryHostMsg_LocalDomainResolverCallback(
46668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)          id, success, address_ipv4, address_ipv6));
467bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
468bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
46968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void ServiceDiscoveryMessageHandler::Send(IPC::Message* msg) {
47068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  utility_task_runner_->PostTask(FROM_HERE,
47168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                 base::Bind(&SendHostMessageOnUtilityThread,
47268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                            msg));
47368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
474ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
475bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}  // namespace local_discovery
476