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
27void 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
32void MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
33        DNSServiceErrorType errorCode, const char *serviceName, const char *regType,
34        const char *domain, void *inContext);
35
36void 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
40void MDnsSdListenerSetHostnameCallback(DNSServiceRef, DNSServiceFlags flags,
41        DNSServiceErrorType errorCode, const char *hostname, void *inContext);
42
43void 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
49class MDnsSdListener : public FrameworkListener {
50public:
51    MDnsSdListener();
52    virtual ~MDnsSdListener() {}
53
54    class Context {
55    public:
56        MDnsSdListener *mListener;
57        int mRefNumber;
58
59        Context(int refNumber, MDnsSdListener *m) {
60            mRefNumber = refNumber;
61            mListener = m;
62        }
63
64        ~Context() {
65        }
66    };
67
68    class Monitor {
69    public:
70        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;
89            Element(int id, Context *context)
90                    : mId(id), mNext(NULL), mContext(context), mReady(0) {}
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
138static int wait_for_property(const char *name, const char *desired_value, int maxwait);
139
140#endif
141