/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _MDNSSDLISTENER_H__
#define _MDNSSDLISTENER_H__
#include <pthread.h>
#include <sysutils/FrameworkListener.h>
#include <dns_sd.h>
#include "NetdCommand.h"
// callbacks
void MDnsSdListenerDiscoverCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
uint32_t interfaceIndex, DNSServiceErrorType errorCode,
const char *serviceName, const char *regType, const char *replyDomain,
void *inContext);
void MDnsSdListenerRegisterCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *serviceName, const char *regType,
const char *domain, void *inContext);
void MDnsSdListenerResolveCallback(DNSServiceRef sdRef, DNSServiceFlags flags, uint32_t interface,
DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, uint16_t port,
uint16_t txtLen, const unsigned char *txtRecord, void *inContext);
void MDnsSdListenerSetHostnameCallback(DNSServiceRef, DNSServiceFlags flags,
DNSServiceErrorType errorCode, const char *hostname, void *inContext);
void MDnsSdListenerGetAddrInfoCallback(DNSServiceRef sdRef, DNSServiceFlags flags,
uint32_t interface, DNSServiceErrorType errorCode, const char *hostname,
const struct sockaddr *const sa, uint32_t ttl, void *inContext);
#define RESCAN "1"
class MDnsSdListener : public FrameworkListener {
public:
MDnsSdListener();
virtual ~MDnsSdListener() {}
static constexpr const char* SOCKET_NAME = "mdns";
class Context {
public:
MDnsSdListener *mListener;
int mRefNumber;
Context(int refNumber, MDnsSdListener *m) {
mRefNumber = refNumber;
mListener = m;
}
~Context() {
}
};
private:
class Monitor {
public:
Monitor();
virtual ~Monitor() {}
DNSServiceRef *allocateServiceRef(int id, Context *c);
void startMonitoring(int id);
DNSServiceRef *lookupServiceRef(int id);
void freeServiceRef(int id);
int startService();
int stopService();
void run();
private:
int rescan(); // returns the number of elements in the poll
class Element {
public:
int mId;
Element *mNext;
DNSServiceRef mRef;
Context *mContext;
int mReady;
Element(int id, Context *context)
: mId(id), mNext(NULL), mContext(context), mReady(0) {}
virtual ~Element() { delete(mContext); }
};
Element *mHead;
int mLiveCount;
struct pollfd *mPollFds;
DNSServiceRef **mPollRefs;
int mPollSize;
int mCtrlSocketPair[2];
pthread_mutex_t mHeadMutex;
};
class Handler : public NetdCommand {
public:
Handler(Monitor *m, MDnsSdListener *listener);
virtual ~Handler();
int runCommand(SocketClient *c, int argc, char** argv);
MDnsSdListener *mListener; // needed for broadcast purposes
private:
void stop(SocketClient *cli, int argc, char **argv, const char *str);
void discover(SocketClient *cli, const char *iface, const char *regType,
const char *domain, const int requestNumber,
const int requestFlags);
void serviceRegister(SocketClient *cli, int requestId, const char *interfaceName,
const char *serviceName, const char *serviceType, const char *domain,
const char *host, int port, int textLen, void *txtRecord);
void resolveService(SocketClient *cli, int requestId,
const char *interfaceName, const char *serviceName, const char *regType,
const char *domain);
void setHostname(SocketClient *cli, int requestId, const char *hostname);
void getAddrInfo(SocketClient *cli, int requestId, const char *interfaceName,
uint32_t protocol, const char *hostname);
int ifaceNameToI(const char *iface);
const char *iToIfaceName(int i);
DNSServiceFlags iToFlags(int i);
int flagsToI(DNSServiceFlags flags);
Monitor *mMonitor;
};
};
#endif