service_discovery_message_handler.cc revision 3551c9c881056c480085172ff9840cab31610854
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
9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/command_line.h"
10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/common/local_discovery/local_discovery_messages.h"
11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/utility/local_discovery/service_discovery_client_impl.h"
12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/common/content_switches.h"
13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/utility/utility_thread.h"
14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(OS_WIN)
16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/lazy_instance.h"
18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "net/base/winsock_init.h"
19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "net/base/winsock_util.h"
20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif  // OS_WIN
22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace local_discovery {
24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace {
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool NeedsSockets() {
28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return !CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox) &&
29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch         CommandLine::ForCurrentProcess()->HasSwitch(
30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch             switches::kUtilityProcessEnableMDns);
31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(OS_WIN)
34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass SocketFactory : public net::PlatformSocketFactory {
36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SocketFactory()
38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      : socket_v4_(NULL),
39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        socket_v6_(NULL) {
40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    net::EnsureWinsockInit();
41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    socket_v4_ = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                           WSA_FLAG_OVERLAPPED);
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    socket_v6_ = WSASocket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP, NULL, 0,
44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                           WSA_FLAG_OVERLAPPED);
45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  void Reset() {
48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (socket_v4_ != INVALID_SOCKET) {
49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      closesocket(socket_v4_);
50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      socket_v4_ = INVALID_SOCKET;
51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (socket_v6_ != INVALID_SOCKET) {
53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      closesocket(socket_v6_);
54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      socket_v6_ = INVALID_SOCKET;
55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual ~SocketFactory() {
59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Reset();
60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  virtual SOCKET CreateSocket(int family, int type, int protocol) OVERRIDE {
63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    SOCKET result = INVALID_SOCKET;
64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (type != SOCK_DGRAM && protocol != IPPROTO_UDP) {
65ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      NOTREACHED();
66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    } else if (family == AF_INET) {
67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      std::swap(result, socket_v4_);
68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    } else if (family == AF_INET6) {
69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      std::swap(result, socket_v6_);
70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return result;
72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SOCKET socket_v4_;
75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  SOCKET socket_v6_;
76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
77bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch private:
78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(SocketFactory);
79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbase::LazyInstance<SocketFactory>
82ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    g_local_discovery_socket_factory = LAZY_INSTANCE_INITIALIZER;
83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass ScopedSocketFactorySetter {
85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ScopedSocketFactorySetter() {
87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (NeedsSockets()) {
88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      net::PlatformSocketFactory::SetInstance(
89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          &g_local_discovery_socket_factory.Get());
90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ~ScopedSocketFactorySetter() {
94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (NeedsSockets()) {
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      net::PlatformSocketFactory::SetInstance(NULL);
96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      g_local_discovery_socket_factory.Get().Reset();
97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  static void Initialize() {
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (NeedsSockets()) {
102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      g_local_discovery_socket_factory.Get();
103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch private:
107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DISALLOW_COPY_AND_ASSIGN(ScopedSocketFactorySetter);
108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#else  // OS_WIN
111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochclass ScopedSocketFactorySetter {
113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public:
114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ScopedSocketFactorySetter() {}
115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  static void Initialize() {
117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // TODO(vitalybuka) : implement socket access from sandbox for other
118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // platforms.
119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    DCHECK(!NeedsSockets());
120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch};
122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif  // OS_WIN
124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SendServiceResolved(uint64 id, ServiceResolver::RequestStatus status,
126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                         const ServiceDescription& description) {
127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  content::UtilityThread::Get()->Send(
128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new LocalDiscoveryHostMsg_ResolverCallback(id, status, description));
129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid SendServiceUpdated(uint64 id, ServiceWatcher::UpdateType update,
132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                        const std::string& name) {
133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  content::UtilityThread::Get()->Send(
134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new LocalDiscoveryHostMsg_WatcherCallback(id, update, name));
135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
137bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid SendLocalDomainResolved(uint64 id, bool success,
138bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                             const net::IPAddressNumber& address) {
139bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  content::UtilityThread::Get()->Send(
140bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      new LocalDiscoveryHostMsg_LocalDomainResolverCallback(
141bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          id, success, address));
142bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}  // namespace
145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochServiceDiscoveryMessageHandler::ServiceDiscoveryMessageHandler() {
147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochServiceDiscoveryMessageHandler::~ServiceDiscoveryMessageHandler() {
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  DCHECK(!discovery_thread_);
151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::PreSandboxStartup() {
154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ScopedSocketFactorySetter::Initialize();
155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::InitializeMdns() {
158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (service_discovery_client_ || mdns_client_)
159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  mdns_client_ = net::MDnsClient::CreateDefault();
162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  {
163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    // Temporarily redirect network code to use pre-created sockets.
164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ScopedSocketFactorySetter socket_factory_setter;
165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (!mdns_client_->StartListening())
166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      return;
167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_discovery_client_.reset(
170ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      new local_discovery::ServiceDiscoveryClientImpl(mdns_client_.get()));
171ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
172ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
173ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ServiceDiscoveryMessageHandler::InitializeThread() {
174ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (discovery_task_runner_)
175ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return true;
176ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (discovery_thread_)
177ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return false;
178ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  utility_task_runner_ = base::MessageLoop::current()->message_loop_proxy();
179ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  discovery_thread_.reset(new base::Thread("ServiceDiscoveryThread"));
180ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  base::Thread::Options thread_options(base::MessageLoop::TYPE_IO, 0);
181ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (discovery_thread_->StartWithOptions(thread_options)) {
182ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    discovery_task_runner_ = discovery_thread_->message_loop_proxy();
183ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    discovery_task_runner_->PostTask(FROM_HERE,
184ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        base::Bind(&ServiceDiscoveryMessageHandler::InitializeMdns,
185ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                    base::Unretained(this)));
186ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
187ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return discovery_task_runner_ != NULL;
188ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
189ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
190ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool ServiceDiscoveryMessageHandler::OnMessageReceived(
191ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const IPC::Message& message) {
192ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  bool handled = true;
193ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  IPC_BEGIN_MESSAGE_MAP(ServiceDiscoveryMessageHandler, message)
194ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_StartWatcher, OnStartWatcher)
195ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DiscoverServices, OnDiscoverServices)
196ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DestroyWatcher, OnDestroyWatcher)
197ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_ResolveService, OnResolveService)
198ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DestroyResolver, OnDestroyResolver)
199bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_ResolveLocalDomain,
200bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                        OnResolveLocalDomain)
201bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_DestroyLocalDomainResolver,
202bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                        OnDestroyLocalDomainResolver)
2033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IPC_MESSAGE_HANDLER(LocalDiscoveryMsg_ShutdownLocalDiscovery,
2043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                        ShutdownLocalDiscovery)
205ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    IPC_MESSAGE_UNHANDLED(handled = false)
206ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  IPC_END_MESSAGE_MAP()
207ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return handled;
208ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
209ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::PostTask(
211ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const tracked_objects::Location& from_here,
212ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const base::Closure& task) {
213ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!InitializeThread())
214ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
215ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  discovery_task_runner_->PostTask(from_here, task);
216ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
217ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnStartWatcher(
219ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
220ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_type) {
221ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
222ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::StartWatcher,
223ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id, service_type));
224ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
225ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
226ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDiscoverServices(uint64 id,
227ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                        bool force_update) {
228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
229ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::DiscoverServices,
230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id, force_update));
231ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
232ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
233ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDestroyWatcher(uint64 id) {
234ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
235ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::DestroyWatcher,
236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id));
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnResolveService(
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_name) {
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::ResolveService,
244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id, service_name));
245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDestroyResolver(uint64 id) {
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  PostTask(FROM_HERE,
249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::DestroyResolver,
250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                      base::Unretained(this), id));
251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
253bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::OnResolveLocalDomain(
254bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    uint64 id, const std::string& domain,
255bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    net::AddressFamily address_family) {
256bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    PostTask(FROM_HERE,
257bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch           base::Bind(&ServiceDiscoveryMessageHandler::ResolveLocalDomain,
258bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                      base::Unretained(this), id, domain, address_family));
259bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
260bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
261bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::OnDestroyLocalDomainResolver(uint64 id) {
262bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  PostTask(FROM_HERE,
263bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch           base::Bind(
264bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch               &ServiceDiscoveryMessageHandler::DestroyLocalDomainResolver,
265bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch               base::Unretained(this), id));
266bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
267bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::StartWatcher(
269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_type) {
271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(!ContainsKey(service_watchers_, id));
274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<ServiceWatcher> watcher(
275ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      service_discovery_client_->CreateServiceWatcher(
276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          service_type,
277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          base::Bind(&ServiceDiscoveryMessageHandler::OnServiceUpdated,
278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     base::Unretained(this), id)));
279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  watcher->Start();
280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_watchers_[id].reset(watcher.release());
281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
282ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
283ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::DiscoverServices(uint64 id,
284ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                                                      bool force_update) {
285ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
286ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
287ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(ContainsKey(service_watchers_, id));
288ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_watchers_[id]->DiscoverNewServices(force_update);
289ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
290ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
291ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::DestroyWatcher(uint64 id) {
292ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
293ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
294ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(ContainsKey(service_watchers_, id));
295ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_watchers_.erase(id);
296ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
297ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
298ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::ResolveService(
299ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
300ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& service_name) {
301ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
302ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
303ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(!ContainsKey(service_resolvers_, id));
304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<ServiceResolver> resolver(
305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      service_discovery_client_->CreateServiceResolver(
306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          service_name,
307ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          base::Bind(&ServiceDiscoveryMessageHandler::OnServiceResolved,
308ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch                     base::Unretained(this), id)));
309ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  resolver->StartResolving();
310ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_resolvers_[id].reset(resolver.release());
311ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
312ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
313ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::DestroyResolver(uint64 id) {
314ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  if (!service_discovery_client_)
315ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    return;
316ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(ContainsKey(service_resolvers_, id));
317ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  service_resolvers_.erase(id);
318ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
319ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
320bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::ResolveLocalDomain(
321bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    uint64 id,
322bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    const std::string& domain,
323bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    net::AddressFamily address_family) {
324bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (!service_discovery_client_)
325bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    return;
326bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(!ContainsKey(local_domain_resolvers_, id));
327bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  scoped_ptr<LocalDomainResolver> resolver(
328bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch      service_discovery_client_->CreateLocalDomainResolver(
329bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          domain, address_family,
330bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch          base::Bind(&ServiceDiscoveryMessageHandler::OnLocalDomainResolved,
331bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                     base::Unretained(this), id)));
332bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  resolver->Start();
333bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  local_domain_resolvers_[id].reset(resolver.release());
334bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
335bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
336bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::DestroyLocalDomainResolver(uint64 id) {
337bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  if (!service_discovery_client_)
338bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    return;
339bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(ContainsKey(local_domain_resolvers_, id));
340bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  local_domain_resolvers_.erase(id);
341bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
342bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
3433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ServiceDiscoveryMessageHandler::ShutdownLocalDiscovery() {
3443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  discovery_task_runner_->PostTask(
3453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      FROM_HERE,
3463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      base::Bind(&ServiceDiscoveryMessageHandler::ShutdownOnIOThread,
3473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                 base::Unretained(this)));
3483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // This will wait for message loop to drain, so ShutdownOnIOThread will
3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // definitely be called.
3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  discovery_thread_.reset();
3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void ServiceDiscoveryMessageHandler::ShutdownOnIOThread() {
3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  service_watchers_.clear();
3563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  service_resolvers_.clear();
3573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  local_domain_resolvers_.clear();
3583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
3593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  service_discovery_client_.reset();
3603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  mdns_client_.reset();
3613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
3623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
363ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnServiceUpdated(
364ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
365ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ServiceWatcher::UpdateType update,
366ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& name) {
367ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(service_discovery_client_);
368ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  utility_task_runner_->PostTask(FROM_HERE,
369ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::Bind(&SendServiceUpdated, id, update, name));
370ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
371ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
372ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid ServiceDiscoveryMessageHandler::OnServiceResolved(
373ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    uint64 id,
374ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ServiceResolver::RequestStatus status,
375ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const ServiceDescription& description) {
376ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(service_discovery_client_);
377ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  utility_task_runner_->PostTask(FROM_HERE,
378ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      base::Bind(&SendServiceResolved, id, status, description));
379ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
380ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
381bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdochvoid ServiceDiscoveryMessageHandler::OnLocalDomainResolved(
382bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    uint64 id,
383bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    bool success,
384bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch    const net::IPAddressNumber& address) {
385bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  DCHECK(service_discovery_client_);
386bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch  utility_task_runner_->PostTask(FROM_HERE, base::Bind(&SendLocalDomainResolved,
387bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch                                                       id, success, address));
388bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}
389bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch
390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
391bbcdd45c55eb7c4641ab97aef9889b0fc828e7d3Ben Murdoch}  // namespace local_discovery
392