blob: e373172ce30e578e6dad3cc8fe959cd0b4f396ea [file] [log] [blame]
/*
* Copyright (c) 2017, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/**
* @file
* This file includes definition for MDNS service based on avahi.
*/
#ifndef OTBR_AGENT_MDNS_AVAHI_HPP_
#define OTBR_AGENT_MDNS_AVAHI_HPP_
#include <vector>
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/domain.h>
#include <avahi-common/watch.h>
#include "mdns.hpp"
/**
* @addtogroup border-router-mdns
*
* @brief
* This module includes definition for avahi-based MDNS service.
*
* @{
*/
/**
* This structure implements AvahiWatch.
*
*/
struct AvahiWatch
{
int mFd; ///< The file descriptor to watch.
AvahiWatchEvent mEvents; ///< The interested events.
int mHappened; ///< The events happened.
AvahiWatchCallback mCallback; ///< The function to be called when interested events happened on mFd.
void * mContext; ///< A pointer to application-specific context.
void * mPoller; ///< The poller created this watch.
/**
* The constructor to initialize an Avahi watch.
*
* @param[in] aFd The file descriptor to watch.
* @param[in] aEvents The events to watch.
* @param[in] aCallback The function to be called when events happend on this file descriptor.
* @param[in] aContext A pointer to application-specific context.
* @param[in] aPoller The Poller this watcher belongs to.
*
*/
AvahiWatch(int aFd, AvahiWatchEvent aEvents, AvahiWatchCallback aCallback, void *aContext, void *aPoller)
: mFd(aFd)
, mEvents(aEvents)
, mCallback(aCallback)
, mContext(aContext)
, mPoller(aPoller)
{
}
};
/**
* This structure implements the AvahiTimeout.
*
*/
struct AvahiTimeout
{
unsigned long mTimeout; ///< Absolute time when this timer timeout.
AvahiTimeoutCallback mCallback; ///< The function to be called when timeout.
void * mContext; ///< The pointer to application-specific context.
void * mPoller; ///< The poller created this timer.
/**
* The constructor to initialize an AvahiTimeout.
*
* @param[in] aTimeout A pointer to the time after which the callback should be called.
* @param[in] aCallback The function to be called after timeout.
* @param[in] aContext A pointer to application-specific context.
* @param[in] aPoller The Poller this timeout belongs to.
*
*/
AvahiTimeout(const struct timeval *aTimeout, AvahiTimeoutCallback aCallback, void *aContext, void *aPoller);
};
namespace otbr {
namespace Mdns {
/**
* This class implements the AvahiPoll.
*
*/
class Poller
{
public:
/**
* The constructor to initialize a Poller.
*
*/
Poller(void);
/**
* This method updates the fd_set and timeout for mainloop.
*
* @param[inout] aReadFdSet A reference to fd_set for polling read.
* @param[inout] aWriteFdSet A reference to fd_set for polling write.
* @param[inout] aErrorFdSet A reference to fd_set for polling error.
* @param[inout] aMaxFd A reference to the max file descriptor.
* @param[inout] aTimeout A reference to the timeout.
*
*/
void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, fd_set &aErrorFdSet, int &aMaxFd, timeval &aTimeout);
/**
* This method performs avahi poll processing.
*
* @param[in] aReadFdSet A reference to read file descriptors.
* @param[in] aWriteFdSet A reference to write file descriptors.
* @param[in] aErrorFdSet A reference to error file descriptors.
*
*/
void Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet, const fd_set &aErrorFdSet);
/**
* This method returns the AvahiPoll.
*
* @returns A pointer to the AvahiPoll.
*
*/
const AvahiPoll *GetAvahiPoll(void) const { return &mAvahiPoller; }
private:
typedef std::vector<AvahiWatch *> Watches;
typedef std::vector<AvahiTimeout *> Timers;
static AvahiWatch * WatchNew(const struct AvahiPoll *aPoller,
int aFd,
AvahiWatchEvent aEvent,
AvahiWatchCallback aCallback,
void * aContext);
AvahiWatch * WatchNew(int aFd, AvahiWatchEvent aEvent, AvahiWatchCallback aCallback, void *aContext);
static void WatchUpdate(AvahiWatch *aWatch, AvahiWatchEvent aEvent);
static AvahiWatchEvent WatchGetEvents(AvahiWatch *aWatch);
static void WatchFree(AvahiWatch *aWatch);
void WatchFree(AvahiWatch &aWatch);
static AvahiTimeout * TimeoutNew(const AvahiPoll * aPoller,
const struct timeval *aTimeout,
AvahiTimeoutCallback aCallback,
void * aContext);
AvahiTimeout * TimeoutNew(const struct timeval *aTimeout, AvahiTimeoutCallback aCallback, void *aContext);
static void TimeoutUpdate(AvahiTimeout *aTimer, const struct timeval *aTimeout);
static void TimeoutFree(AvahiTimeout *aTimer);
void TimeoutFree(AvahiTimeout &aTimer);
Watches mWatches;
Timers mTimers;
AvahiPoll mAvahiPoller;
};
/**
* This class implements MDNS service with avahi.
*
*/
class PublisherAvahi : public Publisher
{
public:
/**
* The constructor to initialize a Publisher.
*
* @param[in] aProtocol The protocol used for publishing. IPv4, IPv6 or both.
* @param[in] aHost The name of host residing the services to be published.
NULL to use default.
* @param[in] aDomain The domain of the host. NULL to use default.
* @param[in] aHandler The function to be called when state changes.
* @param[in] aContext A pointer to application-specific context.
*
*/
PublisherAvahi(int aProtocol, const char *aHost, const char *aDomain, StateHandler aHandler, void *aContext);
~PublisherAvahi(void);
/**
* This method publishes or updates a service.
*
* @note only text record can be updated.
*
* @param[in] aName The name of this service.
* @param[in] aType The type of this service.
* @param[in] aPort The port number of this service.
* @param[in] ... Pointers to null-terminated string of key and value for text record.
* The last argument must be NULL.
*
* @retval OTBR_ERROR_NONE Successfully published or updated the service.
* @retval OTBR_ERROR_ERRNO Failed to publish or update the service.
*
*/
otbrError PublishService(uint16_t aPort, const char *aName, const char *aType, ...);
/**
* This method starts the MDNS service.
*
* @retval OTBR_ERROR_NONE Successfully started MDNS service;
* @retval OTBR_ERROR_MDNS Failed to start MDNS service.
*
*/
otbrError Start(void);
/**
* This method checks if publisher has been started.
*
* @retval true Already started.
* @retval false Not started.
*
*/
bool IsStarted(void) const;
/**
* This method stops the MDNS service.
*
*/
void Stop(void);
/**
* This method performs avahi poll processing.
*
* @param[in] aReadFdSet A reference to read file descriptors.
* @param[in] aWriteFdSet A reference to write file descriptors.
* @param[in] aErrorFdSet A reference to error file descriptors.
*
*/
void Process(const fd_set &aReadFdSet, const fd_set &aWriteFdSet, const fd_set &aErrorFdSet);
/**
* This method updates the fd_set and timeout for mainloop.
*
* @param[inout] aReadFdSet A reference to fd_set for polling read.
* @param[inout] aWriteFdSet A reference to fd_set for polling write.
* @param[inout] aErrorFdSet A reference to fd_set for polling error.
* @param[inout] aMaxFd A reference to the max file descriptor.
* @param[inout] aTimeout A reference to the timeout.
*
*/
void UpdateFdSet(fd_set &aReadFdSet, fd_set &aWriteFdSet, fd_set &aErrorFdSet, int &aMaxFd, timeval &aTimeout);
private:
enum
{
kMaxSizeOfTxtRecord = 128,
kMaxSizeOfServiceName = AVAHI_LABEL_MAX,
kMaxSizeOfHost = AVAHI_LABEL_MAX,
kMaxSizeOfDomain = AVAHI_LABEL_MAX,
kMaxSizeOfServiceType = AVAHI_LABEL_MAX,
};
struct Service
{
char mName[kMaxSizeOfServiceName];
char mType[kMaxSizeOfServiceType];
uint16_t mPort;
};
typedef std::vector<Service> Services;
static void HandleClientState(AvahiClient *aClient, AvahiClientState aState, void *aContext);
void HandleClientState(AvahiClient *aClient, AvahiClientState aState);
void CreateGroup(AvahiClient *aClient);
static void HandleGroupState(AvahiEntryGroup *aGroup, AvahiEntryGroupState aState, void *aContext);
void HandleGroupState(AvahiEntryGroup *aGroup, AvahiEntryGroupState aState);
Services mServices;
AvahiClient * mClient;
AvahiEntryGroup *mGroup;
Poller mPoller;
int mProtocol;
const char * mHost;
const char * mDomain;
State mState;
StateHandler mStateHandler;
void * mContext;
};
} // namespace Mdns
} // namespace otbr
/**
* @}
*/
#endif // OTBR_AGENT_MDNS_AVAHI_HPP_