blob: a44b065d4225790f57dd3c79f61e4f3cc3c407b2 [file] [log] [blame]
Irfan Sheriff7d024d32012-03-22 17:01:39 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.server;
18
19import android.content.Context;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070020import android.content.ContentResolver;
21import android.content.Intent;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070022import android.content.pm.PackageManager;
Irfan Sheriff919aca52012-06-01 16:44:13 -070023import android.database.ContentObserver;
Irfan Sheriff22af38c2012-05-03 16:44:27 -070024import android.net.nsd.NsdServiceInfo;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070025import android.net.nsd.DnsSdTxtRecord;
26import android.net.nsd.INsdManager;
27import android.net.nsd.NsdManager;
28import android.os.Binder;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070029import android.os.Message;
30import android.os.Messenger;
Dianne Hackborn5ac72a22012-08-29 18:32:08 -070031import android.os.UserHandle;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070032import android.provider.Settings;
Philip P. Moltmann312c61e2016-03-16 10:15:39 -070033import android.util.Base64;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070034import android.util.Slog;
Irfan Sheriff22af38c2012-05-03 16:44:27 -070035import android.util.SparseArray;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070036
37import java.io.FileDescriptor;
38import java.io.PrintWriter;
Irfan Sheriff817388e2012-04-11 14:52:19 -070039import java.net.InetAddress;
Irfan Sheriff817388e2012-04-11 14:52:19 -070040import java.util.HashMap;
Irfan Sheriff817388e2012-04-11 14:52:19 -070041import java.util.concurrent.CountDownLatch;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070042
Irfan Sheriff7d024d32012-03-22 17:01:39 -070043import com.android.internal.util.AsyncChannel;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070044import com.android.internal.util.Protocol;
45import com.android.internal.util.State;
46import com.android.internal.util.StateMachine;
Christopher Lane771cd652014-04-14 16:31:27 -070047import com.android.server.NativeDaemonConnector.Command;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070048
49/**
50 * Network Service Discovery Service handles remote service discovery operation requests by
51 * implementing the INsdManager interface.
52 *
53 * @hide
54 */
55public class NsdService extends INsdManager.Stub {
56 private static final String TAG = "NsdService";
57 private static final String MDNS_TAG = "mDnsConnector";
58
Joe Onorato12acbd72016-02-01 17:49:31 -080059 private static final boolean DBG = false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070060
61 private Context mContext;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070062 private ContentResolver mContentResolver;
63 private NsdStateMachine mNsdStateMachine;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070064
65 /**
66 * Clients receiving asynchronous messages
67 */
Irfan Sheriff817388e2012-04-11 14:52:19 -070068 private HashMap<Messenger, ClientInfo> mClients = new HashMap<Messenger, ClientInfo>();
Irfan Sheriff7d024d32012-03-22 17:01:39 -070069
Irfan Sheriff22af38c2012-05-03 16:44:27 -070070 /* A map from unique id to client info */
71 private SparseArray<ClientInfo> mIdToClientInfoMap= new SparseArray<ClientInfo>();
72
Irfan Sheriff7d024d32012-03-22 17:01:39 -070073 private AsyncChannel mReplyChannel = new AsyncChannel();
74
Irfan Sheriff817388e2012-04-11 14:52:19 -070075 private int INVALID_ID = 0;
76 private int mUniqueId = 1;
77
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070078 private static final int BASE = Protocol.BASE_NSD_MANAGER;
Irfan Sheriff22af38c2012-05-03 16:44:27 -070079 private static final int CMD_TO_STRING_COUNT = NsdManager.RESOLVE_SERVICE - BASE + 1;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070080 private static String[] sCmdToString = new String[CMD_TO_STRING_COUNT];
Irfan Sheriff7d024d32012-03-22 17:01:39 -070081
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070082 static {
83 sCmdToString[NsdManager.DISCOVER_SERVICES - BASE] = "DISCOVER";
84 sCmdToString[NsdManager.STOP_DISCOVERY - BASE] = "STOP-DISCOVER";
85 sCmdToString[NsdManager.REGISTER_SERVICE - BASE] = "REGISTER";
86 sCmdToString[NsdManager.UNREGISTER_SERVICE - BASE] = "UNREGISTER";
87 sCmdToString[NsdManager.RESOLVE_SERVICE - BASE] = "RESOLVE";
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070088 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -070089
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070090 private static String cmdToString(int cmd) {
91 cmd -= BASE;
92 if ((cmd >= 0) && (cmd < sCmdToString.length)) {
93 return sCmdToString[cmd];
94 } else {
95 return null;
Irfan Sheriff7d024d32012-03-22 17:01:39 -070096 }
97 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -070098
99 private class NsdStateMachine extends StateMachine {
100
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700101 private final DefaultState mDefaultState = new DefaultState();
102 private final DisabledState mDisabledState = new DisabledState();
103 private final EnabledState mEnabledState = new EnabledState();
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700104
105 @Override
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700106 protected String getWhatToString(int what) {
107 return cmdToString(what);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700108 }
109
Irfan Sheriff919aca52012-06-01 16:44:13 -0700110 /**
111 * Observes the NSD on/off setting, and takes action when changed.
112 */
113 private void registerForNsdSetting() {
114 ContentObserver contentObserver = new ContentObserver(this.getHandler()) {
115 @Override
116 public void onChange(boolean selfChange) {
117 if (isNsdEnabled()) {
118 mNsdStateMachine.sendMessage(NsdManager.ENABLE);
119 } else {
120 mNsdStateMachine.sendMessage(NsdManager.DISABLE);
121 }
122 }
123 };
124
125 mContext.getContentResolver().registerContentObserver(
Jeff Sharkey625239a2012-09-26 22:03:49 -0700126 Settings.Global.getUriFor(Settings.Global.NSD_ON),
Irfan Sheriff919aca52012-06-01 16:44:13 -0700127 false, contentObserver);
128 }
129
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700130 NsdStateMachine(String name) {
131 super(name);
132 addState(mDefaultState);
133 addState(mDisabledState, mDefaultState);
134 addState(mEnabledState, mDefaultState);
135 if (isNsdEnabled()) {
136 setInitialState(mEnabledState);
137 } else {
138 setInitialState(mDisabledState);
139 }
Wink Savillebbf30dfd2012-05-29 12:40:46 -0700140 setLogRecSize(25);
Irfan Sheriff919aca52012-06-01 16:44:13 -0700141 registerForNsdSetting();
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700142 }
143
144 class DefaultState extends State {
145 @Override
146 public boolean processMessage(Message msg) {
Dave Plattf31760c2014-03-07 14:48:22 -0800147 ClientInfo cInfo = null;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700148 switch (msg.what) {
149 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
150 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
151 AsyncChannel c = (AsyncChannel) msg.obj;
152 if (DBG) Slog.d(TAG, "New client listening to asynchronous messages");
153 c.sendMessage(AsyncChannel.CMD_CHANNEL_FULLY_CONNECTED);
Dave Plattf31760c2014-03-07 14:48:22 -0800154 cInfo = new ClientInfo(c, msg.replyTo);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700155 mClients.put(msg.replyTo, cInfo);
156 } else {
157 Slog.e(TAG, "Client connection failure, error=" + msg.arg1);
158 }
159 break;
160 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Dave Plattf31760c2014-03-07 14:48:22 -0800161 switch (msg.arg1) {
162 case AsyncChannel.STATUS_SEND_UNSUCCESSFUL:
163 Slog.e(TAG, "Send failed, client connection lost");
164 break;
165 case AsyncChannel.STATUS_REMOTE_DISCONNECTION:
166 if (DBG) Slog.d(TAG, "Client disconnected");
167 break;
168 default:
169 if (DBG) Slog.d(TAG, "Client connection lost with reason: " + msg.arg1);
170 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700171 }
Dave Plattf31760c2014-03-07 14:48:22 -0800172 cInfo = mClients.get(msg.replyTo);
173 if (cInfo != null) {
174 cInfo.expungeAllRequests();
175 mClients.remove(msg.replyTo);
176 }
177 //Last client
178 if (mClients.size() == 0) {
179 stopMDnsDaemon();
180 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700181 break;
182 case AsyncChannel.CMD_CHANNEL_FULL_CONNECTION:
183 AsyncChannel ac = new AsyncChannel();
184 ac.connect(mContext, getHandler(), msg.replyTo);
185 break;
186 case NsdManager.DISCOVER_SERVICES:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700187 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
188 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700189 break;
190 case NsdManager.STOP_DISCOVERY:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700191 replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
192 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700193 break;
194 case NsdManager.REGISTER_SERVICE:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700195 replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
196 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700197 break;
198 case NsdManager.UNREGISTER_SERVICE:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700199 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
200 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700201 break;
202 case NsdManager.RESOLVE_SERVICE:
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700203 replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
204 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700205 break;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700206 case NsdManager.NATIVE_DAEMON_EVENT:
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700207 default:
208 Slog.e(TAG, "Unhandled " + msg);
209 return NOT_HANDLED;
210 }
211 return HANDLED;
212 }
213 }
214
215 class DisabledState extends State {
216 @Override
217 public void enter() {
218 sendNsdStateChangeBroadcast(false);
219 }
220
221 @Override
222 public boolean processMessage(Message msg) {
223 switch (msg.what) {
224 case NsdManager.ENABLE:
225 transitionTo(mEnabledState);
226 break;
227 default:
228 return NOT_HANDLED;
229 }
230 return HANDLED;
231 }
232 }
233
234 class EnabledState extends State {
235 @Override
236 public void enter() {
237 sendNsdStateChangeBroadcast(true);
238 if (mClients.size() > 0) {
239 startMDnsDaemon();
240 }
241 }
242
243 @Override
244 public void exit() {
245 if (mClients.size() > 0) {
246 stopMDnsDaemon();
247 }
248 }
249
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700250 private boolean requestLimitReached(ClientInfo clientInfo) {
251 if (clientInfo.mClientIds.size() >= ClientInfo.MAX_LIMIT) {
252 if (DBG) Slog.d(TAG, "Exceeded max outstanding requests " + clientInfo);
253 return true;
254 }
255 return false;
256 }
257
Dave Plattf31760c2014-03-07 14:48:22 -0800258 private void storeRequestMap(int clientId, int globalId, ClientInfo clientInfo, int what) {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700259 clientInfo.mClientIds.put(clientId, globalId);
Dave Plattf31760c2014-03-07 14:48:22 -0800260 clientInfo.mClientRequests.put(clientId, what);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700261 mIdToClientInfoMap.put(globalId, clientInfo);
262 }
263
264 private void removeRequestMap(int clientId, int globalId, ClientInfo clientInfo) {
265 clientInfo.mClientIds.remove(clientId);
Dave Plattf31760c2014-03-07 14:48:22 -0800266 clientInfo.mClientRequests.remove(clientId);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700267 mIdToClientInfoMap.remove(globalId);
268 }
269
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700270 @Override
271 public boolean processMessage(Message msg) {
272 ClientInfo clientInfo;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700273 NsdServiceInfo servInfo;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700274 boolean result = HANDLED;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700275 int id;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700276 switch (msg.what) {
277 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
278 //First client
279 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL &&
280 mClients.size() == 0) {
281 startMDnsDaemon();
282 }
283 result = NOT_HANDLED;
284 break;
285 case AsyncChannel.CMD_CHANNEL_DISCONNECTED:
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700286 result = NOT_HANDLED;
287 break;
288 case NsdManager.DISABLE:
289 //TODO: cleanup clients
290 transitionTo(mDisabledState);
291 break;
292 case NsdManager.DISCOVER_SERVICES:
293 if (DBG) Slog.d(TAG, "Discover services");
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700294 servInfo = (NsdServiceInfo) msg.obj;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700295 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700296
297 if (requestLimitReached(clientInfo)) {
298 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
299 NsdManager.FAILURE_MAX_LIMIT);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700300 break;
301 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700302
303 id = getUniqueId();
304 if (discoverServices(id, servInfo.getServiceType())) {
305 if (DBG) {
306 Slog.d(TAG, "Discover " + msg.arg2 + " " + id +
307 servInfo.getServiceType());
308 }
Dave Plattf31760c2014-03-07 14:48:22 -0800309 storeRequestMap(msg.arg2, id, clientInfo, msg.what);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700310 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_STARTED, servInfo);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700311 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700312 stopServiceDiscovery(id);
313 replyToMessage(msg, NsdManager.DISCOVER_SERVICES_FAILED,
314 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700315 }
316 break;
317 case NsdManager.STOP_DISCOVERY:
318 if (DBG) Slog.d(TAG, "Stop service discovery");
319 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700320
321 try {
322 id = clientInfo.mClientIds.get(msg.arg2).intValue();
323 } catch (NullPointerException e) {
324 replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
325 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700326 break;
327 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700328 removeRequestMap(msg.arg2, id, clientInfo);
329 if (stopServiceDiscovery(id)) {
330 replyToMessage(msg, NsdManager.STOP_DISCOVERY_SUCCEEDED);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700331 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700332 replyToMessage(msg, NsdManager.STOP_DISCOVERY_FAILED,
333 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700334 }
335 break;
336 case NsdManager.REGISTER_SERVICE:
337 if (DBG) Slog.d(TAG, "Register service");
338 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700339 if (requestLimitReached(clientInfo)) {
340 replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
341 NsdManager.FAILURE_MAX_LIMIT);
342 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700343 }
344
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700345 id = getUniqueId();
346 if (registerService(id, (NsdServiceInfo) msg.obj)) {
347 if (DBG) Slog.d(TAG, "Register " + msg.arg2 + " " + id);
Dave Plattf31760c2014-03-07 14:48:22 -0800348 storeRequestMap(msg.arg2, id, clientInfo, msg.what);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700349 // Return success after mDns reports success
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700350 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700351 unregisterService(id);
352 replyToMessage(msg, NsdManager.REGISTER_SERVICE_FAILED,
353 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700354 }
355 break;
356 case NsdManager.UNREGISTER_SERVICE:
357 if (DBG) Slog.d(TAG, "unregister service");
358 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700359 try {
360 id = clientInfo.mClientIds.get(msg.arg2).intValue();
361 } catch (NullPointerException e) {
362 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
363 NsdManager.FAILURE_INTERNAL_ERROR);
364 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700365 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700366 removeRequestMap(msg.arg2, id, clientInfo);
367 if (unregisterService(id)) {
368 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_SUCCEEDED);
369 } else {
370 replyToMessage(msg, NsdManager.UNREGISTER_SERVICE_FAILED,
371 NsdManager.FAILURE_INTERNAL_ERROR);
372 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700373 break;
374 case NsdManager.RESOLVE_SERVICE:
375 if (DBG) Slog.d(TAG, "Resolve service");
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700376 servInfo = (NsdServiceInfo) msg.obj;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700377 clientInfo = mClients.get(msg.replyTo);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700378
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700379
380 if (clientInfo.mResolvedService != null) {
381 replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
382 NsdManager.FAILURE_ALREADY_ACTIVE);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700383 break;
384 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700385
386 id = getUniqueId();
387 if (resolveService(id, servInfo)) {
388 clientInfo.mResolvedService = new NsdServiceInfo();
Dave Plattf31760c2014-03-07 14:48:22 -0800389 storeRequestMap(msg.arg2, id, clientInfo, msg.what);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700390 } else {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700391 replyToMessage(msg, NsdManager.RESOLVE_SERVICE_FAILED,
392 NsdManager.FAILURE_INTERNAL_ERROR);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700393 }
394 break;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700395 case NsdManager.NATIVE_DAEMON_EVENT:
396 NativeEvent event = (NativeEvent) msg.obj;
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700397 if (!handleNativeEvent(event.code, event.raw, event.cooked)) {
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700398 result = NOT_HANDLED;
399 }
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700400 break;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700401 default:
402 result = NOT_HANDLED;
403 break;
404 }
405 return result;
406 }
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700407
408 private boolean handleNativeEvent(int code, String raw, String[] cooked) {
409 boolean handled = true;
410 NsdServiceInfo servInfo;
411 int id = Integer.parseInt(cooked[1]);
412 ClientInfo clientInfo = mIdToClientInfoMap.get(id);
413 if (clientInfo == null) {
414 Slog.e(TAG, "Unique id with no client mapping: " + id);
415 handled = false;
416 return handled;
417 }
418
419 /* This goes in response as msg.arg2 */
Christopher Lane5a577902014-04-25 18:39:07 -0700420 int clientId = clientInfo.getClientId(id);
421 if (clientId < 0) {
Vinit Deshapnde8ed09e82013-06-25 19:45:03 -0700422 // This can happen because of race conditions. For example,
423 // SERVICE_FOUND may race with STOP_SERVICE_DISCOVERY,
424 // and we may get in this situation.
425 Slog.d(TAG, "Notification for a listener that is no longer active: " + id);
426 handled = false;
427 return handled;
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700428 }
Vinit Deshapnde8ed09e82013-06-25 19:45:03 -0700429
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700430 switch (code) {
431 case NativeResponseCode.SERVICE_FOUND:
432 /* NNN uniqueId serviceName regType domain */
433 if (DBG) Slog.d(TAG, "SERVICE_FOUND Raw: " + raw);
Christopher Laneb72d8b42014-03-17 16:35:45 -0700434 servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700435 clientInfo.mChannel.sendMessage(NsdManager.SERVICE_FOUND, 0,
436 clientId, servInfo);
437 break;
438 case NativeResponseCode.SERVICE_LOST:
439 /* NNN uniqueId serviceName regType domain */
440 if (DBG) Slog.d(TAG, "SERVICE_LOST Raw: " + raw);
Christopher Laneb72d8b42014-03-17 16:35:45 -0700441 servInfo = new NsdServiceInfo(cooked[2], cooked[3]);
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700442 clientInfo.mChannel.sendMessage(NsdManager.SERVICE_LOST, 0,
443 clientId, servInfo);
444 break;
445 case NativeResponseCode.SERVICE_DISCOVERY_FAILED:
446 /* NNN uniqueId errorCode */
447 if (DBG) Slog.d(TAG, "SERVICE_DISC_FAILED Raw: " + raw);
448 clientInfo.mChannel.sendMessage(NsdManager.DISCOVER_SERVICES_FAILED,
449 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
450 break;
451 case NativeResponseCode.SERVICE_REGISTERED:
452 /* NNN regId serviceName regType */
453 if (DBG) Slog.d(TAG, "SERVICE_REGISTERED Raw: " + raw);
Christopher Laneb72d8b42014-03-17 16:35:45 -0700454 servInfo = new NsdServiceInfo(cooked[2], null);
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700455 clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_SUCCEEDED,
456 id, clientId, servInfo);
457 break;
458 case NativeResponseCode.SERVICE_REGISTRATION_FAILED:
459 /* NNN regId errorCode */
460 if (DBG) Slog.d(TAG, "SERVICE_REGISTER_FAILED Raw: " + raw);
461 clientInfo.mChannel.sendMessage(NsdManager.REGISTER_SERVICE_FAILED,
462 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
463 break;
464 case NativeResponseCode.SERVICE_UPDATED:
465 /* NNN regId */
466 break;
467 case NativeResponseCode.SERVICE_UPDATE_FAILED:
468 /* NNN regId errorCode */
469 break;
470 case NativeResponseCode.SERVICE_RESOLVED:
471 /* NNN resolveId fullName hostName port txtlen txtdata */
472 if (DBG) Slog.d(TAG, "SERVICE_RESOLVED Raw: " + raw);
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700473 int index = 0;
474 while (index < cooked[2].length() && cooked[2].charAt(index) != '.') {
475 if (cooked[2].charAt(index) == '\\') {
476 ++index;
477 }
478 ++index;
479 }
480 if (index >= cooked[2].length()) {
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700481 Slog.e(TAG, "Invalid service found " + raw);
482 break;
483 }
484 String name = cooked[2].substring(0, index);
485 String rest = cooked[2].substring(index);
486 String type = rest.replace(".local.", "");
487
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700488 name = unescape(name);
489
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700490 clientInfo.mResolvedService.setServiceName(name);
491 clientInfo.mResolvedService.setServiceType(type);
492 clientInfo.mResolvedService.setPort(Integer.parseInt(cooked[4]));
Philip P. Moltmann312c61e2016-03-16 10:15:39 -0700493 clientInfo.mResolvedService.setTxtRecords(cooked[6]);
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700494
495 stopResolveService(id);
Vinit Deshapnde40387242013-11-12 15:36:37 -0800496 removeRequestMap(clientId, id, clientInfo);
497
498 int id2 = getUniqueId();
499 if (getAddrInfo(id2, cooked[3])) {
Dave Plattf31760c2014-03-07 14:48:22 -0800500 storeRequestMap(clientId, id2, clientInfo, NsdManager.RESOLVE_SERVICE);
Vinit Deshapnde40387242013-11-12 15:36:37 -0800501 } else {
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700502 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
503 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700504 clientInfo.mResolvedService = null;
505 }
506 break;
507 case NativeResponseCode.SERVICE_RESOLUTION_FAILED:
508 /* NNN resolveId errorCode */
509 if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw);
510 stopResolveService(id);
511 removeRequestMap(clientId, id, clientInfo);
512 clientInfo.mResolvedService = null;
513 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
514 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
515 break;
516 case NativeResponseCode.SERVICE_GET_ADDR_FAILED:
517 /* NNN resolveId errorCode */
518 stopGetAddrInfo(id);
519 removeRequestMap(clientId, id, clientInfo);
520 clientInfo.mResolvedService = null;
521 if (DBG) Slog.d(TAG, "SERVICE_RESOLVE_FAILED Raw: " + raw);
522 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
523 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
524 break;
525 case NativeResponseCode.SERVICE_GET_ADDR_SUCCESS:
526 /* NNN resolveId hostname ttl addr */
527 if (DBG) Slog.d(TAG, "SERVICE_GET_ADDR_SUCCESS Raw: " + raw);
528 try {
529 clientInfo.mResolvedService.setHost(InetAddress.getByName(cooked[4]));
530 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_SUCCEEDED,
531 0, clientId, clientInfo.mResolvedService);
532 } catch (java.net.UnknownHostException e) {
533 clientInfo.mChannel.sendMessage(NsdManager.RESOLVE_SERVICE_FAILED,
534 NsdManager.FAILURE_INTERNAL_ERROR, clientId);
535 }
536 stopGetAddrInfo(id);
537 removeRequestMap(clientId, id, clientInfo);
538 clientInfo.mResolvedService = null;
539 break;
540 default:
541 handled = false;
542 break;
543 }
544 return handled;
545 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700546 }
547 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700548
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700549 private String unescape(String s) {
550 StringBuilder sb = new StringBuilder(s.length());
551 for (int i = 0; i < s.length(); ++i) {
552 char c = s.charAt(i);
553 if (c == '\\') {
554 if (++i >= s.length()) {
555 Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
556 break;
557 }
558 c = s.charAt(i);
559 if (c != '.' && c != '\\') {
560 if (i + 2 >= s.length()) {
561 Slog.e(TAG, "Unexpected end of escape sequence in: " + s);
562 break;
563 }
564 c = (char) ((c-'0') * 100 + (s.charAt(i+1)-'0') * 10 + (s.charAt(i+2)-'0'));
565 i += 2;
566 }
567 }
568 sb.append(c);
569 }
570 return sb.toString();
571 }
572
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700573 private NativeDaemonConnector mNativeConnector;
574 private final CountDownLatch mNativeDaemonConnected = new CountDownLatch(1);
575
576 private NsdService(Context context) {
577 mContext = context;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700578 mContentResolver = context.getContentResolver();
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700579
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700580 mNativeConnector = new NativeDaemonConnector(new NativeCallbackReceiver(), "mdns", 10,
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800581 MDNS_TAG, 25, null);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700582
583 mNsdStateMachine = new NsdStateMachine(TAG);
584 mNsdStateMachine.start();
585
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700586 Thread th = new Thread(mNativeConnector, MDNS_TAG);
587 th.start();
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700588 }
589
590 public static NsdService create(Context context) throws InterruptedException {
591 NsdService service = new NsdService(context);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700592 service.mNativeDaemonConnected.await();
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700593 return service;
594 }
595
596 public Messenger getMessenger() {
Irfan Sheriff92784672012-04-13 12:15:41 -0700597 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INTERNET,
598 "NsdService");
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700599 return new Messenger(mNsdStateMachine.getHandler());
600 }
601
602 public void setEnabled(boolean enable) {
603 mContext.enforceCallingOrSelfPermission(android.Manifest.permission.CONNECTIVITY_INTERNAL,
604 "NsdService");
Jeff Sharkey625239a2012-09-26 22:03:49 -0700605 Settings.Global.putInt(mContentResolver, Settings.Global.NSD_ON, enable ? 1 : 0);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700606 if (enable) {
607 mNsdStateMachine.sendMessage(NsdManager.ENABLE);
608 } else {
609 mNsdStateMachine.sendMessage(NsdManager.DISABLE);
610 }
611 }
612
613 private void sendNsdStateChangeBroadcast(boolean enabled) {
Irfan Sheriff54ac7a52012-04-19 10:26:34 -0700614 final Intent intent = new Intent(NsdManager.ACTION_NSD_STATE_CHANGED);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700615 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
616 if (enabled) {
617 intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_ENABLED);
618 } else {
619 intent.putExtra(NsdManager.EXTRA_NSD_STATE, NsdManager.NSD_STATE_DISABLED);
620 }
Dianne Hackborn5ac72a22012-08-29 18:32:08 -0700621 mContext.sendStickyBroadcastAsUser(intent, UserHandle.ALL);
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700622 }
623
624 private boolean isNsdEnabled() {
Jeff Sharkey625239a2012-09-26 22:03:49 -0700625 boolean ret = Settings.Global.getInt(mContentResolver, Settings.Global.NSD_ON, 1) == 1;
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700626 if (DBG) Slog.d(TAG, "Network service discovery enabled " + ret);
627 return ret;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700628 }
629
Irfan Sheriff817388e2012-04-11 14:52:19 -0700630 private int getUniqueId() {
631 if (++mUniqueId == INVALID_ID) return ++mUniqueId;
632 return mUniqueId;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700633 }
634
Sreeram Ramachandran03666c72014-07-19 23:21:46 -0700635 /* These should be in sync with system/netd/server/ResponseCode.h */
Irfan Sheriff817388e2012-04-11 14:52:19 -0700636 class NativeResponseCode {
637 public static final int SERVICE_DISCOVERY_FAILED = 602;
638 public static final int SERVICE_FOUND = 603;
639 public static final int SERVICE_LOST = 604;
640
641 public static final int SERVICE_REGISTRATION_FAILED = 605;
642 public static final int SERVICE_REGISTERED = 606;
643
644 public static final int SERVICE_RESOLUTION_FAILED = 607;
645 public static final int SERVICE_RESOLVED = 608;
646
647 public static final int SERVICE_UPDATED = 609;
648 public static final int SERVICE_UPDATE_FAILED = 610;
649
650 public static final int SERVICE_GET_ADDR_FAILED = 611;
651 public static final int SERVICE_GET_ADDR_SUCCESS = 612;
652 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700653
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700654 private class NativeEvent {
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700655 final int code;
656 final String raw;
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700657 final String[] cooked;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700658
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700659 NativeEvent(int code, String raw, String[] cooked) {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700660 this.code = code;
661 this.raw = raw;
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700662 this.cooked = cooked;
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700663 }
664 }
665
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700666 class NativeCallbackReceiver implements INativeDaemonConnectorCallbacks {
667 public void onDaemonConnected() {
668 mNativeDaemonConnected.countDown();
669 }
670
Dianne Hackborn77b987f2014-02-26 16:20:52 -0800671 public boolean onCheckHoldWakeLock(int code) {
672 return false;
673 }
674
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700675 public boolean onEvent(int code, String raw, String[] cooked) {
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700676 // TODO: NDC translates a message to a callback, we could enhance NDC to
677 // directly interact with a state machine through messages
Sreeram Ramachandranef128842014-09-03 15:45:59 -0700678 NativeEvent event = new NativeEvent(code, raw, cooked);
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700679 mNsdStateMachine.sendMessage(NsdManager.NATIVE_DAEMON_EVENT, event);
680 return true;
681 }
682 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700683
Irfan Sheriff817388e2012-04-11 14:52:19 -0700684 private boolean startMDnsDaemon() {
685 if (DBG) Slog.d(TAG, "startMDnsDaemon");
686 try {
687 mNativeConnector.execute("mdnssd", "start-service");
688 } catch(NativeDaemonConnectorException e) {
689 Slog.e(TAG, "Failed to start daemon" + e);
690 return false;
691 }
692 return true;
693 }
694
695 private boolean stopMDnsDaemon() {
696 if (DBG) Slog.d(TAG, "stopMDnsDaemon");
697 try {
698 mNativeConnector.execute("mdnssd", "stop-service");
699 } catch(NativeDaemonConnectorException e) {
700 Slog.e(TAG, "Failed to start daemon" + e);
701 return false;
702 }
703 return true;
704 }
705
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700706 private boolean registerService(int regId, NsdServiceInfo service) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700707 if (DBG) Slog.d(TAG, "registerService: " + regId + " " + service);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700708 try {
Christopher Laneb72d8b42014-03-17 16:35:45 -0700709 Command cmd = new Command("mdnssd", "register", regId, service.getServiceName(),
Philip P. Moltmann312c61e2016-03-16 10:15:39 -0700710 service.getServiceType(), service.getPort(),
711 Base64.encodeToString(service.getTxtRecord(), Base64.DEFAULT)
712 .replace("\n", ""));
Christopher Laneb72d8b42014-03-17 16:35:45 -0700713
714 mNativeConnector.execute(cmd);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700715 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700716 Slog.e(TAG, "Failed to execute registerService " + e);
717 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700718 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700719 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700720 }
721
Irfan Sheriff817388e2012-04-11 14:52:19 -0700722 private boolean unregisterService(int regId) {
723 if (DBG) Slog.d(TAG, "unregisterService: " + regId);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700724 try {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700725 mNativeConnector.execute("mdnssd", "stop-register", regId);
726 } catch(NativeDaemonConnectorException e) {
727 Slog.e(TAG, "Failed to execute unregisterService " + e);
728 return false;
729 }
730 return true;
731 }
732
733 private boolean updateService(int regId, DnsSdTxtRecord t) {
734 if (DBG) Slog.d(TAG, "updateService: " + regId + " " + t);
735 try {
736 if (t == null) return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700737 mNativeConnector.execute("mdnssd", "update", regId, t.size(), t.getRawData());
738 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700739 Slog.e(TAG, "Failed to updateServices " + e);
740 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700741 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700742 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700743 }
744
Irfan Sheriff817388e2012-04-11 14:52:19 -0700745 private boolean discoverServices(int discoveryId, String serviceType) {
746 if (DBG) Slog.d(TAG, "discoverServices: " + discoveryId + " " + serviceType);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700747 try {
748 mNativeConnector.execute("mdnssd", "discover", discoveryId, serviceType);
749 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700750 Slog.e(TAG, "Failed to discoverServices " + e);
751 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700752 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700753 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700754 }
755
Irfan Sheriff817388e2012-04-11 14:52:19 -0700756 private boolean stopServiceDiscovery(int discoveryId) {
757 if (DBG) Slog.d(TAG, "stopServiceDiscovery: " + discoveryId);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700758 try {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700759 mNativeConnector.execute("mdnssd", "stop-discover", discoveryId);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700760 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700761 Slog.e(TAG, "Failed to stopServiceDiscovery " + e);
762 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700763 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700764 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700765 }
766
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700767 private boolean resolveService(int resolveId, NsdServiceInfo service) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700768 if (DBG) Slog.d(TAG, "resolveService: " + resolveId + " " + service);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700769 try {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700770 mNativeConnector.execute("mdnssd", "resolve", resolveId, service.getServiceName(),
771 service.getServiceType(), "local.");
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700772 } catch(NativeDaemonConnectorException e) {
Irfan Sheriff817388e2012-04-11 14:52:19 -0700773 Slog.e(TAG, "Failed to resolveService " + e);
774 return false;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700775 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700776 return true;
777 }
778
779 private boolean stopResolveService(int resolveId) {
780 if (DBG) Slog.d(TAG, "stopResolveService: " + resolveId);
781 try {
782 mNativeConnector.execute("mdnssd", "stop-resolve", resolveId);
783 } catch(NativeDaemonConnectorException e) {
784 Slog.e(TAG, "Failed to stop resolve " + e);
785 return false;
786 }
787 return true;
788 }
789
790 private boolean getAddrInfo(int resolveId, String hostname) {
791 if (DBG) Slog.d(TAG, "getAdddrInfo: " + resolveId);
792 try {
793 mNativeConnector.execute("mdnssd", "getaddrinfo", resolveId, hostname);
794 } catch(NativeDaemonConnectorException e) {
795 Slog.e(TAG, "Failed to getAddrInfo " + e);
796 return false;
797 }
798 return true;
799 }
800
801 private boolean stopGetAddrInfo(int resolveId) {
802 if (DBG) Slog.d(TAG, "stopGetAdddrInfo: " + resolveId);
803 try {
804 mNativeConnector.execute("mdnssd", "stop-getaddrinfo", resolveId);
805 } catch(NativeDaemonConnectorException e) {
806 Slog.e(TAG, "Failed to stopGetAddrInfo " + e);
807 return false;
808 }
809 return true;
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700810 }
811
812 @Override
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700813 public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700814 if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
815 != PackageManager.PERMISSION_GRANTED) {
816 pw.println("Permission Denial: can't dump ServiceDiscoverService from from pid="
817 + Binder.getCallingPid()
818 + ", uid=" + Binder.getCallingUid());
819 return;
820 }
821
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700822 for (ClientInfo client : mClients.values()) {
823 pw.println("Client Info");
824 pw.println(client);
825 }
826
827 mNsdStateMachine.dump(fd, pw, args);
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700828 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700829
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700830 /* arg2 on the source message has an id that needs to be retained in replies
831 * see NsdManager for details */
832 private Message obtainMessage(Message srcMsg) {
833 Message msg = Message.obtain();
834 msg.arg2 = srcMsg.arg2;
835 return msg;
Irfan Sheriff817388e2012-04-11 14:52:19 -0700836 }
837
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700838 private void replyToMessage(Message msg, int what) {
839 if (msg.replyTo == null) return;
840 Message dstMsg = obtainMessage(msg);
841 dstMsg.what = what;
842 mReplyChannel.replyToMessage(msg, dstMsg);
Irfan Sheriff817388e2012-04-11 14:52:19 -0700843 }
844
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700845 private void replyToMessage(Message msg, int what, int arg1) {
846 if (msg.replyTo == null) return;
847 Message dstMsg = obtainMessage(msg);
848 dstMsg.what = what;
849 dstMsg.arg1 = arg1;
850 mReplyChannel.replyToMessage(msg, dstMsg);
851 }
852
853 private void replyToMessage(Message msg, int what, Object obj) {
854 if (msg.replyTo == null) return;
855 Message dstMsg = obtainMessage(msg);
856 dstMsg.what = what;
857 dstMsg.obj = obj;
858 mReplyChannel.replyToMessage(msg, dstMsg);
Irfan Sheriff817388e2012-04-11 14:52:19 -0700859 }
860
861 /* Information tracked per client */
862 private class ClientInfo {
863
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700864 private static final int MAX_LIMIT = 10;
Vairavan Srinivasan6727e732012-08-05 13:14:12 -0700865 private final AsyncChannel mChannel;
866 private final Messenger mMessenger;
Irfan Sheriff817388e2012-04-11 14:52:19 -0700867 /* Remembers a resolved service until getaddrinfo completes */
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700868 private NsdServiceInfo mResolvedService;
869
870 /* A map from client id to unique id sent to mDns */
871 private SparseArray<Integer> mClientIds = new SparseArray<Integer>();
Irfan Sheriff817388e2012-04-11 14:52:19 -0700872
Dave Plattf31760c2014-03-07 14:48:22 -0800873 /* A map from client id to the type of the request we had received */
874 private SparseArray<Integer> mClientRequests = new SparseArray<Integer>();
875
Irfan Sheriff817388e2012-04-11 14:52:19 -0700876 private ClientInfo(AsyncChannel c, Messenger m) {
877 mChannel = c;
878 mMessenger = m;
Irfan Sheriff817388e2012-04-11 14:52:19 -0700879 if (DBG) Slog.d(TAG, "New client, channel: " + c + " messenger: " + m);
880 }
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700881
882 @Override
883 public String toString() {
884 StringBuffer sb = new StringBuffer();
885 sb.append("mChannel ").append(mChannel).append("\n");
886 sb.append("mMessenger ").append(mMessenger).append("\n");
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700887 sb.append("mResolvedService ").append(mResolvedService).append("\n");
Irfan Sheriff22af38c2012-05-03 16:44:27 -0700888 for(int i = 0; i< mClientIds.size(); i++) {
Dave Plattf31760c2014-03-07 14:48:22 -0800889 int clientID = mClientIds.keyAt(i);
890 sb.append("clientId ").append(clientID).
891 append(" mDnsId ").append(mClientIds.valueAt(i)).
892 append(" type ").append(mClientRequests.get(clientID)).append("\n");
Irfan Sheriff3ef889b2012-04-17 23:15:29 -0700893 }
894 return sb.toString();
895 }
Dave Plattf31760c2014-03-07 14:48:22 -0800896
897 // Remove any pending requests from the global map when we get rid of a client,
898 // and send cancellations to the daemon.
899 private void expungeAllRequests() {
900 int globalId, clientId, i;
901 for (i = 0; i < mClientIds.size(); i++) {
902 clientId = mClientIds.keyAt(i);
903 globalId = mClientIds.valueAt(i);
904 mIdToClientInfoMap.remove(globalId);
905 if (DBG) Slog.d(TAG, "Terminating client-ID " + clientId +
906 " global-ID " + globalId + " type " + mClientRequests.get(clientId));
907 switch (mClientRequests.get(clientId)) {
908 case NsdManager.DISCOVER_SERVICES:
909 stopServiceDiscovery(globalId);
910 break;
911 case NsdManager.RESOLVE_SERVICE:
912 stopResolveService(globalId);
913 break;
914 case NsdManager.REGISTER_SERVICE:
915 unregisterService(globalId);
916 break;
917 default:
918 break;
919 }
920 }
921 mClientIds.clear();
922 mClientRequests.clear();
923 }
924
Christopher Lane5a577902014-04-25 18:39:07 -0700925 // mClientIds is a sparse array of listener id -> mDnsClient id. For a given mDnsClient id,
926 // return the corresponding listener id. mDnsClient id is also called a global id.
927 private int getClientId(final int globalId) {
928 // This doesn't use mClientIds.indexOfValue because indexOfValue uses == (not .equals)
929 // while also coercing the int primitives to Integer objects.
930 for (int i = 0, nSize = mClientIds.size(); i < nSize; i++) {
931 int mDnsId = mClientIds.valueAt(i);
932 if (globalId == mDnsId) {
933 return mClientIds.keyAt(i);
934 }
935 }
936 return -1;
937 }
Irfan Sheriff817388e2012-04-11 14:52:19 -0700938 }
Irfan Sheriff7d024d32012-03-22 17:01:39 -0700939}