1 /*
2  * Copyright (C) 2012 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 
17 #ifndef _MDNSSDLISTENER_H__
18 #define _MDNSSDLISTENER_H__
19 
20 #include <pthread.h>
21 #include <sysutils/FrameworkListener.h>
22 #include <dns_sd.h>
23 
24 #include "NetdCommand.h"
25 
26 // callbacks
27 void MDnsSdListenerDiscoverCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
28         uint32_t interfaceIndex, DNSServiceErrorType errorCode,
29         const char *serviceName, const char *regType, const char *replyDomain,
30         void *inContext);
31 
32 void MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
33         DNSServiceErrorType errorCode, const char *serviceName, const char *regType,
34         const char *domain, void *inContext);
35 
36 void MDnsSdListenerResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interface,
37         DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port,
38         uint16_t txtLen, const unsigned char *txtRecord, void *inContext);
39 
40 void MDnsSdListenerSetHostnameCallback(DNSServiceRef, DNSServiceFlags flags,
41         DNSServiceErrorType errorCode, const char *hostname, void *inContext);
42 
43 void MDnsSdListenerGetAddrInfoCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
44         uint32_t interface, DNSServiceErrorType errorCode, const char *hostname,
45         const struct sockaddr *const sa, uint32_t ttl, void *inContext);
46 
47 #define RESCAN "1"
48 
49 class MDnsSdListener : public FrameworkListener {
50 public:
51     MDnsSdListener();
~MDnsSdListener()52     virtual ~MDnsSdListener() {}
53 
54     class Context {
55     public:
56         MDnsSdListener *mListener;
57         int mRefNumber;
58 
Context(int refNumber,MDnsSdListener * m)59         Context(int refNumber, MDnsSdListener *m) {
60             mRefNumber = refNumber;
61             mListener = m;
62         }
63 
~Context()64         ~Context() {
65         }
66     };
67 
68     class Monitor {
69     public:
70         Monitor();
~Monitor()71         virtual ~Monitor() {}
72         DNSServiceRef *allocateServiceRef(int id, Context *c);
73         void startMonitoring(int id);
74         DNSServiceRef *lookupServiceRef(int id);
75         void freeServiceRef(int id);
76         static void *threadStart(void *handler);
77         int startService();
78         int stopService();
79     private:
80         void run();
81         int rescan(); // returns the number of elements in the poll
82         class Element {
83         public:
84             int mId;
85             Element *mNext;
86             DNSServiceRef mRef;
87             Context *mContext;
88             int mReady;
Element(int id,Context * context)89             Element(int id, Context *context)
90                     : mId(id), mNext(NULL), mContext(context), mReady(0) {}
~Element()91             virtual ~Element() { delete(mContext); }
92         };
93         Element *mHead;
94         int mLiveCount;
95         struct pollfd *mPollFds;
96         DNSServiceRef **mPollRefs;
97         int mPollSize;
98         pthread_t mThread;
99         int mCtrlSocketPair[2];
100         pthread_mutex_t mHeadMutex;
101     };
102 
103     class Handler : public NetdCommand {
104     public:
105         Handler(Monitor *m, MDnsSdListener *listener);
106         virtual ~Handler();
107         int runCommand(SocketClient *c, int argc, char** argv);
108 
109         MDnsSdListener *mListener; // needed for broadcast purposes
110     private:
111         void stop(SocketClient *cli, int argc, char **argv, const char *str);
112 
113         void discover(SocketClient *cli, const char *iface, const char *regType,
114                 const char *domain, const int requestNumber,
115                 const int requestFlags);
116 
117         void serviceRegister(SocketClient *cli, int requestId, const char *interfaceName,
118                 const char *serviceName, const char *serviceType, const char *domain,
119                 const char *host, int port, int textLen, void *txtRecord);
120 
121         void resolveService(SocketClient *cli, int requestId,
122                 const char *interfaceName, const char *serviceName, const char *regType,
123                 const char *domain);
124 
125         void setHostname(SocketClient *cli, int requestId, const char *hostname);
126 
127         void getAddrInfo(SocketClient *cli, int requestId, const char *interfaceName,
128                 uint32_t protocol, const char *hostname);
129 
130         int ifaceNameToI(const char *iface);
131         const char *iToIfaceName(int i);
132         DNSServiceFlags iToFlags(int i);
133         int flagsToI(DNSServiceFlags flags);
134         Monitor *mMonitor;
135     };
136 };
137 
138 #endif
139