1745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt/*
2745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * Copyright (C) 2012 The Android Open Source Project
3745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *
4745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License");
5745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * you may not use this file except in compliance with the License.
6745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * You may obtain a copy of the License at
7745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *
8745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *      http://www.apache.org/licenses/LICENSE-2.0
9745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt *
10745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * Unless required by applicable law or agreed to in writing, software
11745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS,
12745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * See the License for the specific language governing permissions and
14745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt * limitations under the License.
15745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt */
16745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
17745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#ifndef _MDNSSDLISTENER_H__
18745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define _MDNSSDLISTENER_H__
19745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
20745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <pthread.h>
21745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <sysutils/FrameworkListener.h>
22745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include <dns_sd.h>
23745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
24745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#include "NetdCommand.h"
25745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
26745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt// callbacks
27745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerDiscoverCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
28745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        uint32_t interfaceIndex, DNSServiceErrorType errorCode,
29745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        const char *serviceName, const char *regType, const char *replyDomain,
30745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void *inContext);
31745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
32745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
33745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceErrorType errorCode, const char *serviceName, const char *regType,
34745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        const char *domain, void *inContext);
35745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
36745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interface,
37745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port,
38745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        uint16_t txtLen, const unsigned char *txtRecord, void *inContext);
39745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
40745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerSetHostnameCallback(DNSServiceRef, DNSServiceFlags flags,
41745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceErrorType errorCode, const char *hostname, void *inContext);
42745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
43745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltvoid MDnsSdListenerGetAddrInfoCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
44745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        uint32_t interface, DNSServiceErrorType errorCode, const char *hostname,
45745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        const struct sockaddr *const sa, uint32_t ttl, void *inContext);
46745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
47745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#define RESCAN "1"
48745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
49745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltclass MDnsSdListener : public FrameworkListener {
50745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltpublic:
51745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    MDnsSdListener();
52745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    virtual ~MDnsSdListener() {}
53745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
54745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    class Context {
55745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    public:
56745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        MDnsSdListener *mListener;
57745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int mRefNumber;
58745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
59745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        Context(int refNumber, MDnsSdListener *m) {
60745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            mRefNumber = refNumber;
61745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            mListener = m;
62745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        }
63745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
64745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        ~Context() {
65745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        }
66745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    };
67745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
68745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    class Monitor {
69745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    public:
70745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        Monitor();
71745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        virtual ~Monitor() {}
72745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceRef *allocateServiceRef(int id, Context *c);
73745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void startMonitoring(int id);
74745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceRef *lookupServiceRef(int id);
75745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void freeServiceRef(int id);
76745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        static void *threadStart(void *handler);
77745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int startService();
78745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int stopService();
79745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    private:
80745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void run();
81745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int rescan(); // returns the number of elements in the poll
82745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        class Element {
83745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        public:
84745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            int mId;
85745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            Element *mNext;
86745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            DNSServiceRef mRef;
87745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            Context *mContext;
88745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            int mReady;
89745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            Element(int id, Context *context)
90745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                    : mId(id), mNext(NULL), mContext(context), mReady(0) {}
91745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt            virtual ~Element() { delete(mContext); }
92745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        };
93745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        Element *mHead;
94745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int mLiveCount;
95745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        struct pollfd *mPollFds;
96745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceRef **mPollRefs;
97745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int mPollSize;
98745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        pthread_t mThread;
99745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int mCtrlSocketPair[2];
100745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        pthread_mutex_t mHeadMutex;
101745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    };
102745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
103745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    class Handler : public NetdCommand {
104745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    public:
105745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        Handler(Monitor *m, MDnsSdListener *listener);
106745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        virtual ~Handler();
107745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int runCommand(SocketClient *c, int argc, char** argv);
108745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
109745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        MDnsSdListener *mListener; // needed for broadcast purposes
110745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    private:
111745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void stop(SocketClient *cli, int argc, char **argv, const char *str);
112745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
113745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void discover(SocketClient *cli, const char *iface, const char *regType,
114745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                const char *domain, const int requestNumber,
115745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                const int requestFlags);
116745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
117745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void serviceRegister(SocketClient *cli, int requestId, const char *interfaceName,
118745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                const char *serviceName, const char *serviceType, const char *domain,
119745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                const char *host, int port, int textLen, void *txtRecord);
120745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
121745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void resolveService(SocketClient *cli, int requestId,
122745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                const char *interfaceName, const char *serviceName, const char *regType,
123745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                const char *domain);
124745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
125745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void setHostname(SocketClient *cli, int requestId, const char *hostname);
126745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
127745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        void getAddrInfo(SocketClient *cli, int requestId, const char *interfaceName,
128745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt                uint32_t protocol, const char *hostname);
129745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
130745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int ifaceNameToI(const char *iface);
131745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        const char *iToIfaceName(int i);
132745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        DNSServiceFlags iToFlags(int i);
133745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        int flagsToI(DNSServiceFlags flags);
134745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt        Monitor *mMonitor;
135745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt    };
136745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt};
137745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
138745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwaltstatic int wait_for_property(const char *name, const char *desired_value, int maxwait);
139745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt
140745e09fc5694e73920aaad18a626275597bdddb1Robert Greenwalt#endif
141