зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1115480 - Part 1: Implement XPCOM module for mDNSProvider. r=mcmanus
This commit is contained in:
Родитель
9cdc0b26ad
Коммит
7397b7309f
|
@ -281,6 +281,7 @@
|
|||
@RESPATH@/components/necko_file.xpt
|
||||
@RESPATH@/components/necko_ftp.xpt
|
||||
@RESPATH@/components/necko_http.xpt
|
||||
@RESPATH@/components/necko_mdns.xpt
|
||||
@RESPATH@/components/necko_res.xpt
|
||||
@RESPATH@/components/necko_socket.xpt
|
||||
@RESPATH@/components/necko_strconv.xpt
|
||||
|
|
|
@ -286,6 +286,7 @@
|
|||
@RESPATH@/components/necko_file.xpt
|
||||
@RESPATH@/components/necko_ftp.xpt
|
||||
@RESPATH@/components/necko_http.xpt
|
||||
@RESPATH@/components/necko_mdns.xpt
|
||||
@RESPATH@/components/necko_res.xpt
|
||||
@RESPATH@/components/necko_socket.xpt
|
||||
@RESPATH@/components/necko_strconv.xpt
|
||||
|
|
|
@ -395,6 +395,9 @@ DiskInit.h
|
|||
dlfcn.h
|
||||
dlgs.h
|
||||
dl.h
|
||||
#ifdef MOZ_WIDGET_GONK
|
||||
dns_sd.h
|
||||
#endif
|
||||
docobj.h
|
||||
dos/dosextens.h
|
||||
dos.h
|
||||
|
|
|
@ -227,7 +227,7 @@ if test -n "$gonkdir" ; then
|
|||
MOZ_SECUREELEMENT=1
|
||||
;;
|
||||
17|18)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
if test -d "$gonkdir/external/bluetooth/bluez"; then
|
||||
GONK_INCLUDES="$GONK_INCLUDES -I$gonkdir/external/dbus -I$gonkdir/external/bluetooth/bluez/lib"
|
||||
MOZ_B2G_BT=1
|
||||
|
@ -252,7 +252,7 @@ if test -n "$gonkdir" ; then
|
|||
MOZ_SECUREELEMENT=1
|
||||
;;
|
||||
19)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_B2G_CAMERA=1
|
||||
MOZ_B2G_BT=1
|
||||
MOZ_B2G_BT_BLUEDROID=1
|
||||
|
@ -271,7 +271,7 @@ if test -n "$gonkdir" ; then
|
|||
MOZ_FMP4=1
|
||||
;;
|
||||
21|22)
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include"
|
||||
GONK_INCLUDES="-I$gonkdir/frameworks/native/include -I$gonkdir/frameworks/av/include -I$gonkdir/frameworks/av/include/media -I$gonkdir/frameworks/av/include/camera -I$gonkdir/frameworks/native/include/media/openmax -I$gonkdir/frameworks/av/media/libstagefright/include -I$gonkdir/external/mdnsresponder/mDNSShared"
|
||||
MOZ_AUDIO_OFFLOAD=1
|
||||
MOZ_OMX_DECODER=1
|
||||
MOZ_OMX_ENCODER=1
|
||||
|
|
|
@ -213,6 +213,7 @@
|
|||
@BINPATH@/components/necko_file.xpt
|
||||
@BINPATH@/components/necko_ftp.xpt
|
||||
@BINPATH@/components/necko_http.xpt
|
||||
@BINPATH@/components/necko_mdns.xpt
|
||||
@BINPATH@/components/necko_res.xpt
|
||||
@BINPATH@/components/necko_socket.xpt
|
||||
@BINPATH@/components/necko_strconv.xpt
|
||||
|
|
|
@ -0,0 +1,665 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "MDNSResponderReply.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "nsComponentManagerUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsDNSServiceInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIProperty.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsNetCID.h"
|
||||
#include "nsSocketTransportService2.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "nsXPCOMCID.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
#include "nsASocketHandler.h"
|
||||
|
||||
inline PRLogModuleInfo*
|
||||
GetOperatorLog()
|
||||
{
|
||||
static PRLogModuleInfo* log = PR_NewLogModule("MDNSResponderOperator");
|
||||
return log;
|
||||
}
|
||||
#undef LOG_I
|
||||
#define LOG_I(...) PR_LOG(GetOperatorLog(), PR_LOG_NOTICE, (__VA_ARGS__))
|
||||
#undef LOG_E
|
||||
#define LOG_E(...) PR_LOG(GetOperatorLog(), PR_LOG_ERROR, (__VA_ARGS__))
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class MDNSResponderOperator::ServiceWatcher final
|
||||
: public nsASocketHandler
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
|
||||
// nsASocketHandler methods
|
||||
virtual void OnSocketReady(PRFileDesc* fd, int16_t outFlags) override
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(fd == mFD);
|
||||
|
||||
if (outFlags & (PR_POLL_ERR | PR_POLL_HUP | PR_POLL_NVAL)) {
|
||||
LOG_E("error polling on listening socket (%p)", fd);
|
||||
mCondition = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
if (!(outFlags & PR_POLL_READ)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DNSServiceProcessResult(mService);
|
||||
}
|
||||
|
||||
virtual void OnSocketDetached(PRFileDesc *fd) override
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
MOZ_ASSERT(fd == mFD);
|
||||
|
||||
if (!mFD) {
|
||||
return;
|
||||
}
|
||||
|
||||
PR_Close(mFD);
|
||||
mFD = nullptr;
|
||||
}
|
||||
|
||||
virtual void IsLocal(bool *aIsLocal) override { *aIsLocal = true; }
|
||||
|
||||
virtual void KeepWhenOffline(bool *aKeepWhenOffline) override
|
||||
{
|
||||
*aKeepWhenOffline = true;
|
||||
}
|
||||
|
||||
virtual uint64_t ByteCountSent() override { return 0; }
|
||||
virtual uint64_t ByteCountReceived() override { return 0; }
|
||||
|
||||
explicit ServiceWatcher(DNSServiceRef aService)
|
||||
: mSts(nullptr)
|
||||
, mService(aService)
|
||||
, mFD(nullptr)
|
||||
, mAttached(false)
|
||||
{
|
||||
if (!gSocketTransportService)
|
||||
{
|
||||
nsCOMPtr<nsISocketTransportService> sts =
|
||||
do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Init()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
|
||||
|
||||
if (!mService) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
mSts = gSocketTransportService;
|
||||
|
||||
int osfd = DNSServiceRefSockFD(mService);
|
||||
if (osfd == -1) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mFD = PR_ImportFile(osfd);
|
||||
return PostEvent(&ServiceWatcher::OnMsgAttach);
|
||||
}
|
||||
|
||||
void Close()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() != gSocketThread);
|
||||
|
||||
if (mService) {
|
||||
DNSServiceRefDeallocate(mService);
|
||||
mService = nullptr;
|
||||
}
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return;
|
||||
}
|
||||
|
||||
PostEvent(&ServiceWatcher::OnMsgClose);
|
||||
}
|
||||
|
||||
private:
|
||||
~ServiceWatcher() = default;
|
||||
|
||||
nsresult PostEvent(void(ServiceWatcher::*func)(void))
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> ev = NS_NewRunnableMethod(this, func);
|
||||
return gSocketTransportService->Dispatch(ev, NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
void OnMsgClose()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// tear down socket. this signals the STS to detach our socket handler.
|
||||
mCondition = NS_BINDING_ABORTED;
|
||||
|
||||
// if we are attached, then socket transport service will call our
|
||||
// OnSocketDetached method automatically. Otherwise, we have to call it
|
||||
// (and thus close the socket) manually.
|
||||
if (!mAttached) {
|
||||
OnSocketDetached(mFD);
|
||||
}
|
||||
}
|
||||
|
||||
void OnMsgAttach()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
if (NS_FAILED(mCondition)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCondition = TryAttach();
|
||||
|
||||
// if we hit an error while trying to attach then bail...
|
||||
if (NS_FAILED(mCondition)) {
|
||||
NS_ASSERTION(!mAttached, "should not be attached already");
|
||||
OnSocketDetached(mFD);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
nsresult TryAttach()
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!gSocketTransportService) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
//
|
||||
// find out if it is going to be ok to attach another socket to the STS.
|
||||
// if not then we have to wait for the STS to tell us that it is ok.
|
||||
// the notification is asynchronous, which means that when we could be
|
||||
// in a race to call AttachSocket once notified. for this reason, when
|
||||
// we get notified, we just re-enter this function. as a result, we are
|
||||
// sure to ask again before calling AttachSocket. in this way we deal
|
||||
// with the race condition. though it isn't the most elegant solution,
|
||||
// it is far simpler than trying to build a system that would guarantee
|
||||
// FIFO ordering (which wouldn't even be that valuable IMO). see bug
|
||||
// 194402 for more info.
|
||||
//
|
||||
if (!gSocketTransportService->CanAttachSocket()) {
|
||||
nsCOMPtr<nsIRunnable> event =
|
||||
NS_NewRunnableMethod(this, &ServiceWatcher::OnMsgAttach);
|
||||
|
||||
nsresult rv = gSocketTransportService->NotifyWhenCanAttachSocket(event);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// ok, we can now attach our socket to the STS for polling
|
||||
//
|
||||
rv = gSocketTransportService->AttachSocket(mFD, this);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mAttached = true;
|
||||
|
||||
//
|
||||
// now, configure our poll flags for listening...
|
||||
//
|
||||
mPollFlags = (PR_POLL_READ | PR_POLL_EXCEPT);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsRefPtr<nsSocketTransportService> mSts;
|
||||
DNSServiceRef mService;
|
||||
PRFileDesc* mFD;
|
||||
bool mAttached;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(MDNSResponderOperator::ServiceWatcher, nsISupports)
|
||||
|
||||
MDNSResponderOperator::MDNSResponderOperator()
|
||||
: mService(nullptr)
|
||||
, mWatcher(nullptr)
|
||||
, mThread(NS_GetCurrentThread())
|
||||
, mIsCancelled(false)
|
||||
{
|
||||
}
|
||||
|
||||
MDNSResponderOperator::~MDNSResponderOperator()
|
||||
{
|
||||
Stop();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::Start()
|
||||
{
|
||||
if (mIsCancelled) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (IsServing()) {
|
||||
Stop();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::Stop()
|
||||
{
|
||||
mThread = nullptr;
|
||||
return ResetService(nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
MDNSResponderOperator::ResetService(DNSServiceRef aService)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
if (aService != mService) {
|
||||
if (mWatcher) {
|
||||
mWatcher->Close();
|
||||
mWatcher = nullptr;
|
||||
}
|
||||
|
||||
if (aService) {
|
||||
nsRefPtr<ServiceWatcher> watcher = new ServiceWatcher(aService);
|
||||
if (NS_WARN_IF(NS_FAILED(watcher->Init()))) {
|
||||
return rv;
|
||||
}
|
||||
mWatcher = watcher;
|
||||
}
|
||||
|
||||
mService = aService;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
BrowseOperator::BrowseOperator(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceType(aServiceType)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
BrowseOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err = DNSServiceBrowse(&service,
|
||||
0,
|
||||
kDNSServiceInterfaceIndexAny,
|
||||
mServiceType.get(),
|
||||
nullptr,
|
||||
&BrowseReplyRunnable::Reply,
|
||||
this);
|
||||
NS_WARN_IF(kDNSServiceErr_NoError != err);
|
||||
|
||||
if (mListener) {
|
||||
if (kDNSServiceErr_NoError == err) {
|
||||
mListener->OnDiscoveryStarted(mServiceType);
|
||||
} else {
|
||||
mListener->OnStartDiscoveryFailed(mServiceType, err);
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
BrowseOperator::Stop()
|
||||
{
|
||||
bool isServing = IsServing();
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
|
||||
if (isServing && mListener) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener->OnDiscoveryStopped(mServiceType);
|
||||
} else {
|
||||
mListener->OnStopDiscoveryFailed(mServiceType,
|
||||
static_cast<uint32_t>(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
BrowseOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
|
||||
LOG_E("BrowseOperator::Reply (%d)", aErrorCode);
|
||||
if (mListener) {
|
||||
mListener->OnStartDiscoveryFailed(mServiceType, aErrorCode);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo();
|
||||
|
||||
if (NS_WARN_IF(!info)) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aServiceName)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aReplyDomain)))) { return; }
|
||||
|
||||
if (aFlags & kDNSServiceFlagsAdd) {
|
||||
mListener->OnServiceFound(info);
|
||||
} else {
|
||||
mListener->OnServiceLost(info);
|
||||
}
|
||||
}
|
||||
|
||||
RegisterOperator::RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceInfo(aServiceInfo)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
RegisterOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
rv = MDNSResponderOperator::Start();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
uint16_t port;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetPort(&port)))) {
|
||||
return rv;
|
||||
}
|
||||
nsAutoCString type;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = mServiceInfo->GetServiceType(type)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
TXTRecordRef txtRecord;
|
||||
char buf[TXT_BUFFER_SIZE] = { 0 };
|
||||
TXTRecordCreate(&txtRecord, TXT_BUFFER_SIZE, buf);
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> attributes;
|
||||
if (NS_FAILED(rv = mServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
|
||||
LOG_I("register: no attributes");
|
||||
} else {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
if (NS_WARN_IF(NS_FAILED(rv =
|
||||
attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool hasMoreElements;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsCOMPtr<nsISupports> element;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(enumerator->GetNext(getter_AddRefs(element))));
|
||||
nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
|
||||
MOZ_ASSERT(property);
|
||||
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetName(name)));
|
||||
MOZ_ALWAYS_TRUE(NS_SUCCEEDED(property->GetValue(getter_AddRefs(value))));
|
||||
|
||||
nsAutoCString str;
|
||||
if (NS_WARN_IF(NS_FAILED(value->GetAsACString(str)))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TXTRecordSetValue(&txtRecord,
|
||||
/* it's safe because key name is ASCII only. */
|
||||
NS_LossyConvertUTF16toASCII(name).get(),
|
||||
str.Length(),
|
||||
str.get());
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString host;
|
||||
nsAutoCString name;
|
||||
nsAutoCString domain;
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err =
|
||||
DNSServiceRegister(&service,
|
||||
0,
|
||||
0,
|
||||
NS_SUCCEEDED(mServiceInfo->GetServiceName(name)) ?
|
||||
name.get() : nullptr,
|
||||
type.get(),
|
||||
NS_SUCCEEDED(mServiceInfo->GetDomainName(domain)) ?
|
||||
domain.get() : nullptr,
|
||||
NS_SUCCEEDED(mServiceInfo->GetHost(host)) ?
|
||||
host.get() : nullptr,
|
||||
NativeEndian::swapToNetworkOrder(port),
|
||||
TXTRecordGetLength(&txtRecord),
|
||||
TXTRecordGetBytesPtr(&txtRecord),
|
||||
&RegisterReplyRunnable::Reply,
|
||||
this);
|
||||
NS_WARN_IF(kDNSServiceErr_NoError != err);
|
||||
|
||||
TXTRecordDeallocate(&txtRecord);
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
if (mListener) {
|
||||
mListener->OnRegistrationFailed(mServiceInfo, err);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
RegisterOperator::Stop()
|
||||
{
|
||||
bool isServing = IsServing();
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
|
||||
if (isServing && mListener) {
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
mListener->OnServiceUnregistered(mServiceInfo);
|
||||
} else {
|
||||
mListener->OnUnregistrationFailed(mServiceInfo,
|
||||
static_cast<uint32_t>(rv));
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
if (kDNSServiceErr_NoError != aErrorCode) {
|
||||
LOG_E("RegisterOperator::Reply (%d)", aErrorCode);
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceName(aName)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetServiceType(aRegType)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetDomainName(aDomain)))) { return; }
|
||||
|
||||
if (kDNSServiceErr_NoError == aErrorCode) {
|
||||
mListener->OnServiceRegistered(info);
|
||||
} else {
|
||||
mListener->OnRegistrationFailed(info, aErrorCode);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveOperator::ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener)
|
||||
: MDNSResponderOperator()
|
||||
, mServiceInfo(aServiceInfo)
|
||||
, mListener(aListener)
|
||||
, mDeleteProtector()
|
||||
{
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolveOperator::Start()
|
||||
{
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = MDNSResponderOperator::Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsAutoCString name;
|
||||
mServiceInfo->GetServiceName(name);
|
||||
nsAutoCString type;
|
||||
mServiceInfo->GetServiceType(type);
|
||||
nsAutoCString domain;
|
||||
mServiceInfo->GetDomainName(domain);
|
||||
|
||||
LOG_I("Resolve: (%s), (%s), (%s)", name.get(), type.get(), domain.get());
|
||||
|
||||
DNSServiceRef service = nullptr;
|
||||
DNSServiceErrorType err =
|
||||
DNSServiceResolve(&service,
|
||||
0,
|
||||
kDNSServiceInterfaceIndexAny,
|
||||
name.get(),
|
||||
type.get(),
|
||||
domain.get(),
|
||||
(DNSServiceResolveReply)&ResolveReplyRunnable::Reply,
|
||||
this);
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != err)) {
|
||||
if (mListener) {
|
||||
mListener->OnResolveFailed(mServiceInfo, err);
|
||||
}
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mDeleteProtector = this;
|
||||
return ResetService(service);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ResolveOperator::Stop()
|
||||
{
|
||||
nsresult rv = MDNSResponderOperator::Stop();
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
ResolveOperator::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord)
|
||||
{
|
||||
MOZ_ASSERT(GetThread() == NS_GetCurrentThread());
|
||||
|
||||
mDeleteProtector = nullptr;
|
||||
|
||||
if (NS_WARN_IF(kDNSServiceErr_NoError != aErrorCode)) {
|
||||
LOG_E("ResolveOperator::Reply (%d)", aErrorCode);
|
||||
return;
|
||||
}
|
||||
|
||||
// Resolve TXT record
|
||||
int count = TXTRecordGetCount(aTxtLen, aTxtRecord);
|
||||
LOG_I("resolve: txt count = %d, len = %d", count, aTxtLen);
|
||||
nsCOMPtr<nsIWritablePropertyBag2> attributes = nullptr;
|
||||
if (count) {
|
||||
attributes = new nsHashPropertyBag();
|
||||
if (NS_WARN_IF(!attributes)) { return; }
|
||||
for (int i = 0; i < count; ++i) {
|
||||
char key[TXT_BUFFER_SIZE] = { '\0' };
|
||||
uint8_t vSize = 0;
|
||||
const void* value = nullptr;
|
||||
if (kDNSServiceErr_NoError !=
|
||||
TXTRecordGetItemAtIndex(aTxtLen,
|
||||
aTxtRecord,
|
||||
i,
|
||||
TXT_BUFFER_SIZE,
|
||||
key,
|
||||
&vSize,
|
||||
&value)) {
|
||||
break;
|
||||
}
|
||||
|
||||
nsAutoCString str(reinterpret_cast<const char*>(value), vSize);
|
||||
LOG_I("resolve TXT: (%d) %s=%s", vSize, key, str.get());
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(attributes->SetPropertyAsACString(
|
||||
/* it's safe to convert because key name is ASCII only. */
|
||||
NS_ConvertASCIItoUTF16(key),
|
||||
str)))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mListener) { return; }
|
||||
nsCOMPtr<nsIDNSServiceInfo> info = new nsDNSServiceInfo(mServiceInfo);
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetHost(aHostTarget)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetPort(aPort)))) { return; }
|
||||
if (NS_WARN_IF(NS_FAILED(info->SetAttributes(attributes)))) { return; }
|
||||
|
||||
if (kDNSServiceErr_NoError == aErrorCode) {
|
||||
mListener->OnServiceResolved(info);
|
||||
} else {
|
||||
mListener->OnResolveFailed(info, aErrorCode);
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(Stop()));
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,139 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
||||
|
||||
#include "dns_sd.h"
|
||||
#include "mozilla/Atomics.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class MDNSResponderOperator
|
||||
{
|
||||
public:
|
||||
MDNSResponderOperator();
|
||||
|
||||
virtual nsresult Start();
|
||||
virtual nsresult Stop();
|
||||
void Cancel() { mIsCancelled = true; }
|
||||
nsIThread* GetThread() const { return mThread; }
|
||||
|
||||
protected:
|
||||
virtual ~MDNSResponderOperator();
|
||||
|
||||
bool IsServing() const { return mService; }
|
||||
nsresult ResetService(DNSServiceRef aService);
|
||||
|
||||
private:
|
||||
class ServiceWatcher;
|
||||
|
||||
DNSServiceRef mService;
|
||||
nsRefPtr<ServiceWatcher> mWatcher;
|
||||
nsCOMPtr<nsIThread> mThread; // remember caller thread for callback
|
||||
Atomic<bool> mIsCancelled;
|
||||
};
|
||||
|
||||
class BrowseOperator final : private MDNSResponderOperator
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(BrowseOperator)
|
||||
|
||||
BrowseOperator(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::Cancel;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain);
|
||||
|
||||
private:
|
||||
~BrowseOperator() = default;
|
||||
|
||||
nsCString mServiceType;
|
||||
nsCOMPtr<nsIDNSServiceDiscoveryListener> mListener;
|
||||
};
|
||||
|
||||
class RegisterOperator final : private MDNSResponderOperator
|
||||
{
|
||||
enum { TXT_BUFFER_SIZE = 256 };
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(RegisterOperator)
|
||||
|
||||
RegisterOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::Cancel;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain);
|
||||
|
||||
private:
|
||||
~RegisterOperator() = default;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
|
||||
nsCOMPtr<nsIDNSRegistrationListener> mListener;
|
||||
};
|
||||
|
||||
class ResolveOperator final : private MDNSResponderOperator
|
||||
{
|
||||
enum { TXT_BUFFER_SIZE = 256 };
|
||||
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(ResolveOperator)
|
||||
|
||||
ResolveOperator(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener);
|
||||
|
||||
nsresult Start() override;
|
||||
nsresult Stop() override;
|
||||
using MDNSResponderOperator::GetThread;
|
||||
|
||||
void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord);
|
||||
|
||||
private:
|
||||
~ResolveOperator() = default;
|
||||
|
||||
nsCOMPtr<nsIDNSServiceInfo> mServiceInfo;
|
||||
nsCOMPtr<nsIDNSServiceResolveListener> mListener;
|
||||
|
||||
// hold self until callback is made.
|
||||
nsRefPtr<ResolveOperator> mDeleteProtector;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderOperator_h
|
|
@ -0,0 +1,225 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MDNSResponderReply.h"
|
||||
#include "mozilla/Endian.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
BrowseReplyRunnable::BrowseReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain,
|
||||
BrowseOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mInterfaceIndex(aInterfaceIndex)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mServiceName(aServiceName)
|
||||
, mRegType(aRegType)
|
||||
, mReplyDomain(aReplyDomain)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
BrowseReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mInterfaceIndex,
|
||||
mErrorCode,
|
||||
mServiceName,
|
||||
mRegType,
|
||||
mReplyDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
BrowseReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aServiceName,
|
||||
const char* aRegType,
|
||||
const char* aReplyDomain,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
BrowseOperator* obj(reinterpret_cast<BrowseOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new BrowseReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aInterfaceIndex,
|
||||
aErrorCode,
|
||||
nsCString(aServiceName),
|
||||
nsCString(aRegType),
|
||||
nsCString(aReplyDomain),
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
RegisterReplyRunnable::RegisterReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& domain,
|
||||
RegisterOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mName(aName)
|
||||
, mRegType(aRegType)
|
||||
, mDomain(domain)
|
||||
, mContext(aContext)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mErrorCode,
|
||||
mName,
|
||||
mRegType,
|
||||
mDomain);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
RegisterReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aName,
|
||||
const char* aRegType,
|
||||
const char* domain,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
RegisterOperator* obj(reinterpret_cast<RegisterOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new RegisterReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aErrorCode,
|
||||
nsCString(aName),
|
||||
nsCString(aRegType),
|
||||
nsCString(domain),
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
ResolveReplyRunnable::ResolveReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
ResolveOperator* aContext)
|
||||
: mSdRef(aSdRef)
|
||||
, mFlags(aFlags)
|
||||
, mInterfaceIndex(aInterfaceIndex)
|
||||
, mErrorCode(aErrorCode)
|
||||
, mFullname(aFullName)
|
||||
, mHosttarget(aHostTarget)
|
||||
, mPort(aPort)
|
||||
, mTxtLen(aTxtLen)
|
||||
, mTxtRecord(new unsigned char[aTxtLen])
|
||||
, mContext(aContext)
|
||||
{
|
||||
if (mTxtRecord) {
|
||||
memcpy(mTxtRecord.get(), aTxtRecord, aTxtLen);
|
||||
}
|
||||
}
|
||||
|
||||
ResolveReplyRunnable::~ResolveReplyRunnable()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ResolveReplyRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(mContext);
|
||||
mContext->Reply(mSdRef,
|
||||
mFlags,
|
||||
mInterfaceIndex,
|
||||
mErrorCode,
|
||||
mFullname,
|
||||
mHosttarget,
|
||||
mPort,
|
||||
mTxtLen,
|
||||
mTxtRecord.get());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
ResolveReplyRunnable::Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aFullName,
|
||||
const char* aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
void* aContext)
|
||||
{
|
||||
MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
|
||||
|
||||
ResolveOperator* obj(reinterpret_cast<ResolveOperator*>(aContext));
|
||||
if (!obj) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> thread(obj->GetThread());
|
||||
if (!thread) {
|
||||
return;
|
||||
}
|
||||
|
||||
thread->Dispatch(new ResolveReplyRunnable(aSdRef,
|
||||
aFlags,
|
||||
aInterfaceIndex,
|
||||
aErrorCode,
|
||||
nsCString(aFullName),
|
||||
nsCString(aHostTarget),
|
||||
NativeEndian::swapFromNetworkOrder(aPort),
|
||||
aTxtLen,
|
||||
aTxtRecord,
|
||||
obj),
|
||||
NS_DISPATCH_NORMAL);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,128 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
||||
|
||||
#include "dns_sd.h"
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "mozilla/UniquePtr.h"
|
||||
#include "nsIThread.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class BrowseReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
BrowseReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aServiceName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aReplyDomain,
|
||||
BrowseOperator* aContext);
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aServiceName,
|
||||
const char* aRegType,
|
||||
const char* aReplyDomain,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
uint32_t mInterfaceIndex;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mServiceName;
|
||||
nsCString mRegType;
|
||||
nsCString mReplyDomain;
|
||||
BrowseOperator* mContext;
|
||||
};
|
||||
|
||||
class RegisterReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
RegisterReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aName,
|
||||
const nsACString& aRegType,
|
||||
const nsACString& aDomain,
|
||||
RegisterOperator* aContext);
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aName,
|
||||
const char* aRegType,
|
||||
const char* aDomain,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mName;
|
||||
nsCString mRegType;
|
||||
nsCString mDomain;
|
||||
RegisterOperator* mContext;
|
||||
};
|
||||
|
||||
class ResolveReplyRunnable final : public nsRunnable
|
||||
{
|
||||
public:
|
||||
ResolveReplyRunnable(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const nsACString& aFullName,
|
||||
const nsACString& aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
ResolveOperator* aContext);
|
||||
~ResolveReplyRunnable();
|
||||
|
||||
NS_IMETHODIMP Run() override;
|
||||
|
||||
static void Reply(DNSServiceRef aSdRef,
|
||||
DNSServiceFlags aFlags,
|
||||
uint32_t aInterfaceIndex,
|
||||
DNSServiceErrorType aErrorCode,
|
||||
const char* aFullName,
|
||||
const char* aHostTarget,
|
||||
uint16_t aPort,
|
||||
uint16_t aTxtLen,
|
||||
const unsigned char* aTxtRecord,
|
||||
void* aContext);
|
||||
|
||||
private:
|
||||
DNSServiceRef mSdRef;
|
||||
DNSServiceFlags mFlags;
|
||||
uint32_t mInterfaceIndex;
|
||||
DNSServiceErrorType mErrorCode;
|
||||
nsCString mFullname;
|
||||
nsCString mHosttarget;
|
||||
uint16_t mPort;
|
||||
uint16_t mTxtLen;
|
||||
UniquePtr<unsigned char> mTxtRecord;
|
||||
nsRefPtr<ResolveOperator> mContext;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_MDNSResponderReply_h
|
|
@ -0,0 +1,33 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
|
||||
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk' and CONFIG['ANDROID_VERSION'] >= '16':
|
||||
UNIFIED_SOURCES += [
|
||||
'MDNSResponderOperator.cpp',
|
||||
'MDNSResponderReply.cpp',
|
||||
'nsDNSServiceDiscovery.cpp',
|
||||
]
|
||||
|
||||
CXXFLAGS += [
|
||||
'-I%s/%s' % (CONFIG['ANDROID_SOURCE'], d) for d in [
|
||||
'external/mdnsresponder/mDNSShared',
|
||||
]
|
||||
]
|
||||
|
||||
LOCAL_INCLUDES += [
|
||||
'/netwerk/base',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsDNSServiceInfo.cpp',
|
||||
'nsMulticastDNSModule.cpp',
|
||||
]
|
||||
|
||||
FAIL_ON_WARNINGS = True
|
||||
|
||||
include('/ipc/chromium/chromium-config.mozbuild')
|
||||
FINAL_LIBRARY = 'xul'
|
|
@ -0,0 +1,230 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDNSServiceDiscovery.h"
|
||||
#include <cutils/properties.h>
|
||||
#include "MDNSResponderOperator.h"
|
||||
#include "nsICancelable.h"
|
||||
#include "private/pprio.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
StartService()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX] = { '\0' };
|
||||
property_get("init.svc.mdnsd", value, "");
|
||||
|
||||
if (strcmp(value, "running") == 0) {
|
||||
return;
|
||||
}
|
||||
property_set("ctl.start", "mdnsd");
|
||||
}
|
||||
|
||||
void
|
||||
StopService()
|
||||
{
|
||||
char value[PROPERTY_VALUE_MAX] = { '\0' };
|
||||
property_get("init.svc.mdnsd", value, "");
|
||||
|
||||
if (strcmp(value, "stopped") == 0) {
|
||||
return;
|
||||
}
|
||||
property_set("ctl.stop", "mdnsd");
|
||||
}
|
||||
|
||||
class DiscoveryRequest final : public nsICancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
explicit DiscoveryRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSServiceDiscoveryListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~DiscoveryRequest() { Cancel(NS_OK); }
|
||||
|
||||
nsRefPtr<nsDNSServiceDiscovery> mService;
|
||||
nsIDNSServiceDiscoveryListener* mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(DiscoveryRequest, nsICancelable)
|
||||
|
||||
DiscoveryRequest::DiscoveryRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSServiceDiscoveryListener* aListener)
|
||||
: mService(aService)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DiscoveryRequest::Cancel(nsresult aReason)
|
||||
{
|
||||
if (mService) {
|
||||
mService->StopDiscovery(mListener);
|
||||
}
|
||||
|
||||
mService = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
class RegisterRequest final : public nsICancelable
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSICANCELABLE
|
||||
|
||||
explicit RegisterRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSRegistrationListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~RegisterRequest() { Cancel(NS_OK); }
|
||||
|
||||
nsRefPtr<nsDNSServiceDiscovery> mService;
|
||||
nsIDNSRegistrationListener* mListener;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS(RegisterRequest, nsICancelable)
|
||||
|
||||
RegisterRequest::RegisterRequest(nsDNSServiceDiscovery* aService,
|
||||
nsIDNSRegistrationListener* aListener)
|
||||
: mService(aService)
|
||||
, mListener(aListener)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
RegisterRequest::Cancel(nsresult aReason)
|
||||
{
|
||||
if (mService) {
|
||||
mService->UnregisterService(mListener);
|
||||
}
|
||||
|
||||
mService = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace anonymous
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSServiceDiscovery, nsIDNSServiceDiscovery)
|
||||
|
||||
nsresult
|
||||
nsDNSServiceDiscovery::Init()
|
||||
{
|
||||
StartService();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::StartDiscovery(const nsACString& aServiceType,
|
||||
nsIDNSServiceDiscoveryListener* aListener,
|
||||
nsICancelable** aRetVal)
|
||||
{
|
||||
MOZ_ASSERT(aRetVal);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = StopDiscovery(aListener)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<BrowseOperator> browserOp = new BrowseOperator(aServiceType,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = browserOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDiscoveryMap.Put(aListener, browserOp);
|
||||
|
||||
nsCOMPtr<nsICancelable> req = new DiscoveryRequest(this, aListener);
|
||||
req.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::StopDiscovery(nsIDNSServiceDiscoveryListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<BrowseOperator> browserOp;
|
||||
if (!mDiscoveryMap.Get(aListener, getter_AddRefs(browserOp))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
browserOp->Cancel(); // cancel non-started operation
|
||||
if (NS_WARN_IF(NS_FAILED(rv = browserOp->Stop()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mDiscoveryMap.Remove(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::RegisterService(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSRegistrationListener* aListener,
|
||||
nsICancelable** aRetVal)
|
||||
{
|
||||
MOZ_ASSERT(aRetVal);
|
||||
|
||||
nsresult rv;
|
||||
if (NS_WARN_IF(NS_FAILED(rv = UnregisterService(aListener)))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsRefPtr<RegisterOperator> registerOp = new RegisterOperator(aServiceInfo,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = registerOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRegisterMap.Put(aListener, registerOp);
|
||||
|
||||
nsCOMPtr<nsICancelable> req = new RegisterRequest(this, aListener);
|
||||
req.forget(aRetVal);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::UnregisterService(nsIDNSRegistrationListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<RegisterOperator> registerOp;
|
||||
if (!mRegisterMap.Get(aListener, getter_AddRefs(registerOp))) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
registerOp->Cancel(); // cancel non-started operation
|
||||
if (NS_WARN_IF(NS_FAILED(rv = registerOp->Stop()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
mRegisterMap.Remove(aListener);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceDiscovery::ResolveService(nsIDNSServiceInfo* aServiceInfo,
|
||||
nsIDNSServiceResolveListener* aListener)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsRefPtr<ResolveOperator> resolveOp = new ResolveOperator(aServiceInfo,
|
||||
aListener);
|
||||
if (NS_WARN_IF(NS_FAILED(rv = resolveOp->Start()))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
||||
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsRefPtr.h"
|
||||
#include "nsRefPtrHashtable.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class BrowseOperator;
|
||||
class RegisterOperator;
|
||||
|
||||
class nsDNSServiceDiscovery final : public nsIDNSServiceDiscovery
|
||||
{
|
||||
public:
|
||||
NS_DECL_THREADSAFE_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICEDISCOVERY
|
||||
|
||||
explicit nsDNSServiceDiscovery() = default;
|
||||
|
||||
/*
|
||||
** The mDNS service is started in this function. However, the function returns
|
||||
** without waiting. Therefore, all operations before service started will fail
|
||||
** and get error code |kDNSServiceErr_ServiceNotRunning| defined in dns_sd.h.
|
||||
**/
|
||||
nsresult Init();
|
||||
|
||||
nsresult StopDiscovery(nsIDNSServiceDiscoveryListener* aListener);
|
||||
nsresult UnregisterService(nsIDNSRegistrationListener* aListener);
|
||||
|
||||
private:
|
||||
virtual ~nsDNSServiceDiscovery() = default;
|
||||
|
||||
nsRefPtrHashtable<nsISupportsHashKey, BrowseOperator> mDiscoveryMap;
|
||||
nsRefPtrHashtable<nsISupportsHashKey, RegisterOperator> mRegisterMap;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceDiscovery_h
|
|
@ -0,0 +1,183 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsDNSServiceInfo.h"
|
||||
#include "nsHashPropertyBag.h"
|
||||
#include "nsIProperty.h"
|
||||
#include "nsISimpleEnumerator.h"
|
||||
#include "nsISupportsImpl.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
NS_IMPL_ISUPPORTS(nsDNSServiceInfo, nsIDNSServiceInfo)
|
||||
|
||||
nsDNSServiceInfo::nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo)
|
||||
{
|
||||
if (NS_WARN_IF(!aServiceInfo)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString str;
|
||||
uint16_t value;
|
||||
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetHost(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetHost(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetPort(&value))) {
|
||||
NS_WARN_IF(NS_FAILED(SetPort(value)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetServiceName(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetServiceName(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetServiceType(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetServiceType(str)));
|
||||
}
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetDomainName(str))) {
|
||||
NS_WARN_IF(NS_FAILED(SetDomainName(str)));
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPropertyBag2> attributes; // deep copy
|
||||
if (NS_SUCCEEDED(aServiceInfo->GetAttributes(getter_AddRefs(attributes)))) {
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
if (NS_WARN_IF(NS_FAILED(attributes->GetEnumerator(getter_AddRefs(enumerator))))) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIWritablePropertyBag2> newAttributes = new nsHashPropertyBag();
|
||||
|
||||
bool hasMoreElements;
|
||||
while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMoreElements)) &&
|
||||
hasMoreElements) {
|
||||
nsCOMPtr<nsISupports> element;
|
||||
NS_WARN_IF(NS_FAILED(enumerator->GetNext(getter_AddRefs(element))));
|
||||
nsCOMPtr<nsIProperty> property = do_QueryInterface(element);
|
||||
MOZ_ASSERT(property);
|
||||
|
||||
nsAutoString name;
|
||||
nsCOMPtr<nsIVariant> value;
|
||||
NS_WARN_IF(NS_FAILED(property->GetName(name)));
|
||||
NS_WARN_IF(NS_FAILED(property->GetValue(getter_AddRefs(value))));
|
||||
NS_WARN_IF(NS_FAILED(newAttributes->SetPropertyAsInterface(name, value)));
|
||||
}
|
||||
|
||||
NS_WARN_IF(NS_FAILED(SetAttributes(newAttributes)));
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetHost(nsACString& aHost)
|
||||
{
|
||||
if (!mIsHostSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aHost = mHost;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetHost(const nsACString& aHost)
|
||||
{
|
||||
mHost = aHost;
|
||||
mIsHostSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetPort(uint16_t* aPort)
|
||||
{
|
||||
if (NS_WARN_IF(!aPort)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
if (!mIsPortSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
*aPort = mPort;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetPort(uint16_t aPort)
|
||||
{
|
||||
mPort = aPort;
|
||||
mIsPortSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetServiceName(nsACString& aServiceName)
|
||||
{
|
||||
if (!mIsServiceNameSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aServiceName = mServiceName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetServiceName(const nsACString& aServiceName)
|
||||
{
|
||||
mServiceName = aServiceName;
|
||||
mIsServiceNameSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetServiceType(nsACString& aServiceType)
|
||||
{
|
||||
if (!mIsServiceTypeSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aServiceType = mServiceType;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetServiceType(const nsACString& aServiceType)
|
||||
{
|
||||
mServiceType = aServiceType;
|
||||
mIsServiceTypeSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetDomainName(nsACString& aDomainName)
|
||||
{
|
||||
if (!mIsDomainNameSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
aDomainName = mDomainName;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetDomainName(const nsACString& aDomainName)
|
||||
{
|
||||
mDomainName = aDomainName;
|
||||
mIsDomainNameSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::GetAttributes(nsIPropertyBag2** aAttributes)
|
||||
{
|
||||
if (!mIsAttributesSet) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
nsCOMPtr<nsIPropertyBag2> attributes(mAttributes);
|
||||
attributes.forget(aAttributes);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDNSServiceInfo::SetAttributes(nsIPropertyBag2* aAttributes)
|
||||
{
|
||||
mAttributes = aAttributes;
|
||||
mIsAttributesSet = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,48 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
||||
#define mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
||||
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDNSServiceDiscovery.h"
|
||||
#include "nsIPropertyBag2.h"
|
||||
#include "nsString.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
class nsDNSServiceInfo final : public nsIDNSServiceInfo
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIDNSSERVICEINFO
|
||||
|
||||
explicit nsDNSServiceInfo() = default;
|
||||
explicit nsDNSServiceInfo(nsIDNSServiceInfo* aServiceInfo);
|
||||
|
||||
private:
|
||||
virtual ~nsDNSServiceInfo() = default;
|
||||
|
||||
private:
|
||||
nsCString mHost;
|
||||
uint16_t mPort = 0;
|
||||
nsCString mServiceName;
|
||||
nsCString mServiceType;
|
||||
nsCString mDomainName;
|
||||
nsCOMPtr<nsIPropertyBag2> mAttributes;
|
||||
|
||||
bool mIsHostSet = false;
|
||||
bool mIsPortSet = false;
|
||||
bool mIsServiceNameSet = false;
|
||||
bool mIsServiceTypeSet = false;
|
||||
bool mIsDomainNameSet = false;
|
||||
bool mIsAttributesSet = false;
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_netwerk_dns_mdns_libmdns_nsDNSServiceInfo_h
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 16
|
||||
#define ENABLE_DNS_SERVICE_DISCOVERY
|
||||
#endif
|
||||
|
||||
#include "mozilla/ModuleUtils.h"
|
||||
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
#include "nsDNSServiceDiscovery.h"
|
||||
#endif
|
||||
|
||||
#include "nsDNSServiceInfo.h"
|
||||
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
using mozilla::net::nsDNSServiceDiscovery;
|
||||
#define DNSSERVICEDISCOVERY_CID \
|
||||
{0x8df43d23, 0xd3f9, 0x4dd5, \
|
||||
{ 0xb9, 0x65, 0xde, 0x2c, 0xa3, 0xf6, 0xa4, 0x2c }}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsDNSServiceDiscovery, Init)
|
||||
NS_DEFINE_NAMED_CID(DNSSERVICEDISCOVERY_CID);
|
||||
#endif // ENABLE_DNS_SERVICE_DISCOVERY
|
||||
|
||||
using mozilla::net::nsDNSServiceInfo;
|
||||
#define DNSSERVICEINFO_CID \
|
||||
{0x14a50f2b, 0x7ff6, 0x48a5, \
|
||||
{ 0x88, 0xe3, 0x61, 0x5f, 0xd1, 0x11, 0xf5, 0xd3 }}
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsDNSServiceInfo)
|
||||
NS_DEFINE_NAMED_CID(DNSSERVICEINFO_CID);
|
||||
|
||||
static const mozilla::Module::CIDEntry knsDNSServiceDiscoveryCIDs[] = {
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
{ &kDNSSERVICEDISCOVERY_CID, false, nullptr, nsDNSServiceDiscoveryConstructor },
|
||||
#endif
|
||||
{ &kDNSSERVICEINFO_CID, false, nullptr, nsDNSServiceInfoConstructor },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::ContractIDEntry knsDNSServiceDiscoveryContracts[] = {
|
||||
#ifdef ENABLE_DNS_SERVICE_DISCOVERY
|
||||
{ DNSSERVICEDISCOVERY_CONTRACT_ID, &kDNSSERVICEDISCOVERY_CID },
|
||||
#endif
|
||||
{ DNSSERVICEINFO_CONTRACT_ID, &kDNSSERVICEINFO_CID },
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module::CategoryEntry knsDNSServiceDiscoveryCategories[] = {
|
||||
{ nullptr }
|
||||
};
|
||||
|
||||
static const mozilla::Module knsDNSServiceDiscoveryModule = {
|
||||
mozilla::Module::kVersion,
|
||||
knsDNSServiceDiscoveryCIDs,
|
||||
knsDNSServiceDiscoveryContracts,
|
||||
knsDNSServiceDiscoveryCategories
|
||||
};
|
||||
|
||||
NSMODULE_DEFN(nsDNSServiceDiscoveryModule) = &knsDNSServiceDiscoveryModule;
|
|
@ -0,0 +1,13 @@
|
|||
# -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
|
||||
# vim: set filetype=python:
|
||||
# This Source Code Form is subject to the terms of the Mozilla Public
|
||||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += ['libmdns']
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDNSServiceDiscovery.idl',
|
||||
]
|
||||
|
||||
XPIDL_MODULE = 'necko_mdns'
|
|
@ -0,0 +1,213 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "nsISupports.idl"
|
||||
|
||||
interface nsICancelable;
|
||||
interface nsIPropertyBag2;
|
||||
|
||||
/**
|
||||
* Service information
|
||||
*/
|
||||
[scriptable, uuid(112bfa89-1b57-4acf-8287-48e5466c1b39)]
|
||||
interface nsIDNSServiceInfo : nsISupports
|
||||
{
|
||||
/**
|
||||
* The host name of the service. (E.g. "Android.local.")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String host;
|
||||
|
||||
/**
|
||||
* The port number of the service. (E.g. 80)
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute unsigned short port;
|
||||
|
||||
/**
|
||||
* The service name of the service for display. (E.g. "My TV")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String serviceName;
|
||||
|
||||
/**
|
||||
* The type of the service. (E.g. "_http._tcp")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String serviceType;
|
||||
|
||||
/**
|
||||
* The domain name of the service. (E.g. "local.")
|
||||
* @throws NS_ERROR_NOT_INITIALIZED when getting unset value.
|
||||
*/
|
||||
attribute AUTF8String domainName;
|
||||
|
||||
/**
|
||||
* The attributes of the service.
|
||||
*/
|
||||
attribute nsIPropertyBag2 attributes;
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service discovery
|
||||
*/
|
||||
[scriptable, uuid(3025b7f2-97bb-435b-b43d-26731b3f5fc4)]
|
||||
interface nsIDNSServiceDiscoveryListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback when the discovery begins.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
*/
|
||||
void onDiscoveryStarted(in AUTF8String aServiceType);
|
||||
|
||||
/**
|
||||
* Callback when the discovery ends.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
*/
|
||||
void onDiscoveryStopped(in AUTF8String aServiceType);
|
||||
|
||||
/**
|
||||
* Callback when the a service is found.
|
||||
* @param aServiceInfo
|
||||
* the info about the found service, where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceFound(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the a service is lost.
|
||||
* @param aServiceInfo
|
||||
* the info about the lost service, where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceLost(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the discovery cannot start.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onStartDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
|
||||
|
||||
/**
|
||||
* Callback when the discovery cannot stop.
|
||||
* @param aServiceType
|
||||
* the service type of |startDiscovery|.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onStopDiscoveryFailed(in AUTF8String aServiceType, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service registration
|
||||
*/
|
||||
[scriptable, uuid(e165e4be-abf4-4963-a66d-ed3ca116e5e4)]
|
||||
interface nsIDNSRegistrationListener : nsISupports
|
||||
{
|
||||
const long ERROR_SERVICE_NOT_RUNNING = -65563;
|
||||
|
||||
/**
|
||||
* Callback when the service is registered successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the registered service,
|
||||
* where |serviceName|, |aServiceType|, and |domainName| are set.
|
||||
*/
|
||||
void onServiceRegistered(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service is unregistered successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the unregistered service.
|
||||
*/
|
||||
void onServiceUnregistered(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be registered.
|
||||
* @param aServiceInfo
|
||||
* the info about the service to be registered.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onRegistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be unregistered.
|
||||
* @param aServiceInfo
|
||||
* the info about the registered service.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onUnregistrationFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The callback interface for service resolve
|
||||
*/
|
||||
[scriptable, uuid(24ee6408-648e-421d-accf-c6e5adeccf97)]
|
||||
interface nsIDNSServiceResolveListener : nsISupports
|
||||
{
|
||||
/**
|
||||
* Callback when the service is resolved successfully.
|
||||
* @param aServiceInfo
|
||||
* the info about the resolved service, where |host| and |port| are set.
|
||||
*/
|
||||
void onServiceResolved(in nsIDNSServiceInfo aServiceInfo);
|
||||
|
||||
/**
|
||||
* Callback when the service cannot be resolved.
|
||||
* @param aServiceInfo
|
||||
* the info about the service to be resolved.
|
||||
* @param aErrorCode
|
||||
* the error code.
|
||||
*/
|
||||
void onResolveFailed(in nsIDNSServiceInfo aServiceInfo, in long aErrorCode);
|
||||
};
|
||||
|
||||
/**
|
||||
* The interface for DNS service discovery/registration/resolve
|
||||
*/
|
||||
[scriptable, uuid(6487899b-beb1-455a-ba65-e4fd465066d7)]
|
||||
interface nsIDNSServiceDiscovery : nsISupports
|
||||
{
|
||||
/**
|
||||
* Browse for instances of a service.
|
||||
* @param aServiceType
|
||||
* the service type to be discovered, E.g. "_http._tcp".
|
||||
* @param aListener
|
||||
* callback interface for discovery notifications.
|
||||
* @return An object that can be used to cancel the service discovery.
|
||||
*/
|
||||
nsICancelable startDiscovery(in AUTF8String aServiceType, in nsIDNSServiceDiscoveryListener aListener);
|
||||
|
||||
/**
|
||||
* Register a service that is discovered via |startDiscovery| and |resolveService| calls.
|
||||
* @param aServiceInfo
|
||||
* the service information to be registered.
|
||||
* |port| and |aServiceType| are required attributes.
|
||||
* @param aListener
|
||||
* callback interface for registration notifications.
|
||||
* @return An object that can be used to cancel the service registration.
|
||||
*/
|
||||
nsICancelable registerService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSRegistrationListener aListener);
|
||||
|
||||
/**
|
||||
* Resolve a service name discovered via |startDiscovery| to a target host name, port number.
|
||||
* @param aServiceInfo
|
||||
* the service information to be registered.
|
||||
* |serviceName|, |aServiceType|, and |domainName| are required attributes as reported to the |onServiceFound| callback.
|
||||
* @param aListener
|
||||
* callback interface for registration notifications.
|
||||
*/
|
||||
void resolveService(in nsIDNSServiceInfo aServiceInfo, in nsIDNSServiceResolveListener aListener);
|
||||
};
|
||||
|
||||
%{ C++
|
||||
#define DNSSERVICEDISCOVERY_CONTRACT_ID \
|
||||
"@mozilla.org/toolkit/components/mdnsresponder/dns-sd;1"
|
||||
#define DNSSERVICEINFO_CONTRACT_ID \
|
||||
"@mozilla.org/toolkit/components/mdnsresponder/dns-info;1"
|
||||
%}
|
|
@ -4,6 +4,10 @@
|
|||
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
DIRS += [
|
||||
'mdns',
|
||||
]
|
||||
|
||||
XPIDL_SOURCES += [
|
||||
'nsIDNSListener.idl',
|
||||
'nsIDNSRecord.idl',
|
||||
|
|
|
@ -258,6 +258,11 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
|
|||
'sync',
|
||||
]
|
||||
|
||||
if CONFIG['ANDROID_VERSION'] >= '16':
|
||||
OS_LIBS += [
|
||||
'mdnssd',
|
||||
]
|
||||
|
||||
if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
|
||||
OS_LIBS += [
|
||||
'stagefright_foundation',
|
||||
|
|
Загрузка…
Ссылка в новой задаче