1 /*
2  * Copyright (C) 2022 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 package android.net.nsd;
17 
18 import android.annotation.NonNull;
19 import android.net.mdns.aidl.DiscoveryInfo;
20 import android.net.mdns.aidl.GetAddressInfo;
21 import android.net.mdns.aidl.IMDns;
22 import android.net.mdns.aidl.IMDnsEventListener;
23 import android.net.mdns.aidl.RegistrationInfo;
24 import android.net.mdns.aidl.ResolutionInfo;
25 import android.os.RemoteException;
26 import android.os.ServiceSpecificException;
27 import android.util.Log;
28 
29 /**
30  * A manager class for mdns service.
31  *
32  * @hide
33  */
34 public class MDnsManager {
35     private static final String TAG = MDnsManager.class.getSimpleName();
36     private final IMDns mMdns;
37 
38     /** Service name for this. */
39     public static final String MDNS_SERVICE = "mdns";
40 
41     private static final int NO_RESULT = -1;
42     private static final int NETID_UNSET = 0;
43 
MDnsManager(IMDns mdns)44     public MDnsManager(IMDns mdns) {
45         mMdns = mdns;
46     }
47 
48     /**
49      * Start the MDNSResponder daemon.
50      */
startDaemon()51     public void startDaemon() {
52         try {
53             mMdns.startDaemon();
54         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
55             Log.e(TAG, "Start mdns failed.", e);
56         }
57     }
58 
59     /**
60      * Stop the MDNSResponder daemon.
61      */
stopDaemon()62     public void stopDaemon() {
63         try {
64             mMdns.stopDaemon();
65         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
66             Log.e(TAG, "Stop mdns failed.", e);
67         }
68     }
69 
70     /**
71      * Start registering a service.
72      *
73      * @param id The operation ID.
74      * @param serviceName The service name to be registered.
75      * @param registrationType The service type to be registered.
76      * @param port The port on which the service accepts connections.
77      * @param txtRecord The txt record. Refer to {@code NsdServiceInfo#setTxtRecords} for details.
78      * @param interfaceIdx The interface index on which to register the service.
79      * @return {@code true} if registration is successful, else {@code false}.
80      */
registerService(int id, @NonNull String serviceName, @NonNull String registrationType, int port, @NonNull byte[] txtRecord, int interfaceIdx)81     public boolean registerService(int id, @NonNull String serviceName,
82             @NonNull String registrationType, int port, @NonNull byte[] txtRecord,
83             int interfaceIdx) {
84         final RegistrationInfo info = new RegistrationInfo(id, NO_RESULT, serviceName,
85                 registrationType, port, txtRecord, interfaceIdx);
86         try {
87             mMdns.registerService(info);
88         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
89             Log.e(TAG, "Register service failed.", e);
90             return false;
91         }
92         return true;
93     }
94 
95     /**
96      * Start discovering services.
97      *
98      * @param id The operation ID.
99      * @param registrationType The service type to be discovered.
100      * @param interfaceIdx The interface index on which to discover for services.
101      * @return {@code true} if discovery is started successfully, else {@code false}.
102      */
discover(int id, @NonNull String registrationType, int interfaceIdx)103     public boolean discover(int id, @NonNull String registrationType, int interfaceIdx) {
104         final DiscoveryInfo info = new DiscoveryInfo(id, NO_RESULT, "" /* serviceName */,
105                 registrationType, "" /* domainName */, interfaceIdx, NETID_UNSET);
106         try {
107             mMdns.discover(info);
108         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
109             Log.e(TAG, "Discover service failed.", e);
110             return false;
111         }
112         return true;
113     }
114 
115     /**
116      * Start resolving the target service.
117      *
118      * @param id The operation ID.
119      * @param serviceName The service name to be resolved.
120      * @param registrationType The service type to be resolved.
121      * @param domain The service domain to be resolved.
122      * @param interfaceIdx The interface index on which to resolve the service.
123      * @return {@code true} if resolution is started successfully, else {@code false}.
124      */
resolve(int id, @NonNull String serviceName, @NonNull String registrationType, @NonNull String domain, int interfaceIdx)125     public boolean resolve(int id, @NonNull String serviceName, @NonNull String registrationType,
126             @NonNull String domain, int interfaceIdx) {
127         final ResolutionInfo info = new ResolutionInfo(id, NO_RESULT, serviceName,
128                 registrationType, domain, "" /* serviceFullName */, "" /* hostname */, 0 /* port */,
129                 new byte[0] /* txtRecord */, interfaceIdx);
130         try {
131             mMdns.resolve(info);
132         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
133             Log.e(TAG, "Resolve service failed.", e);
134             return false;
135         }
136         return true;
137     }
138 
139     /**
140      * Start getting the target service address.
141      *
142      * @param id The operation ID.
143      * @param hostname The fully qualified domain name of the host to be queried for.
144      * @param interfaceIdx The interface index on which to issue the query.
145      * @return {@code true} if getting address is started successful, else {@code false}.
146      */
getServiceAddress(int id, @NonNull String hostname, int interfaceIdx)147     public boolean getServiceAddress(int id, @NonNull String hostname, int interfaceIdx) {
148         final GetAddressInfo info = new GetAddressInfo(id, NO_RESULT, hostname,
149                 "" /* address */, interfaceIdx, NETID_UNSET);
150         try {
151             mMdns.getServiceAddress(info);
152         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
153             Log.e(TAG, "Get service address failed.", e);
154             return false;
155         }
156         return true;
157     }
158 
159     /**
160      * Stop an operation which was requested before.
161      *
162      * @param id the operation id to be stopped.
163      * @return {@code true} if operation is stopped successfully, else {@code false}.
164      */
stopOperation(int id)165     public boolean stopOperation(int id) {
166         try {
167             mMdns.stopOperation(id);
168         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
169             Log.e(TAG, "Stop operation failed.", e);
170             return false;
171         }
172         return true;
173     }
174 
175     /**
176      * Register an event listener.
177      *
178      * @param listener The listener to be registered.
179      */
registerEventListener(@onNull IMDnsEventListener listener)180     public void registerEventListener(@NonNull IMDnsEventListener listener) {
181         try {
182             mMdns.registerEventListener(listener);
183         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
184             Log.e(TAG, "Register listener failed.", e);
185         }
186     }
187 
188     /**
189      * Unregister an event listener.
190      *
191      * @param listener The listener to be unregistered.
192      */
unregisterEventListener(@onNull IMDnsEventListener listener)193     public void unregisterEventListener(@NonNull IMDnsEventListener listener) {
194         try {
195             mMdns.unregisterEventListener(listener);
196         } catch (RemoteException | ServiceSpecificException | UnsupportedOperationException e) {
197             Log.e(TAG, "Unregister listener failed.", e);
198         }
199     }
200 }
201