1 /* -*- Mode: C; tab-width: 4 -*-
3 * Copyright (c) 2009 Apple Computer, Inc. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 #include "CDNSSDService.h"
19 #include "nsThreadUtils.h"
20 #include "nsIEventTarget.h"
21 #include "private/pprio.h"
26 NS_IMPL_ISUPPORTS2(CDNSSDService
, IDNSSDService
, nsIRunnable
)
28 CDNSSDService::CDNSSDService()
40 if ( DNSServiceCreateConnection( &m_mainRef
) != kDNSServiceErr_NoError
)
42 err
= NS_ERROR_FAILURE
;
46 if ( ( m_fileDesc
= PR_ImportTCPSocket( DNSServiceRefSockFD( m_mainRef
) ) ) == NULL
)
48 err
= NS_ERROR_FAILURE
;
52 if ( ( m_threadPool
= PR_CreateThreadPool( 1, 1, 8192 ) ) == NULL
)
54 err
= NS_ERROR_FAILURE
;
58 err
= SetupNotifications();
69 CDNSSDService::CDNSSDService( DNSServiceRef ref
, nsISupports
* listener
)
75 m_listener( listener
),
82 CDNSSDService::~CDNSSDService()
89 CDNSSDService::Cleanup()
95 PR_CancelJob( m_job
);
99 if ( m_threadPool
!= NULL
)
101 PR_ShutdownThreadPool( m_threadPool
);
105 if ( m_fileDesc
!= NULL
)
107 PR_Close( m_fileDesc
);
113 DNSServiceRefDeallocate( m_mainRef
);
121 DNSServiceRefDeallocate( m_subRef
);
129 CDNSSDService::SetupNotifications()
131 NS_PRECONDITION( m_threadPool
!= NULL
, "m_threadPool is NULL" );
132 NS_PRECONDITION( m_fileDesc
!= NULL
, "m_fileDesc is NULL" );
133 NS_PRECONDITION( m_job
== NULL
, "m_job is not NULL" );
135 m_iod
.socket
= m_fileDesc
;
136 m_iod
.timeout
= PR_INTERVAL_MAX
;
137 m_job
= PR_QueueJob_Read( m_threadPool
, &m_iod
, Read
, this, PR_FALSE
);
138 return ( m_job
) ? NS_OK
: NS_ERROR_FAILURE
;
142 /* IDNSSDService browse (in long interfaceIndex, in AString regtype, in AString domain, in IDNSSDBrowseListener listener); */
144 CDNSSDService::Browse(PRInt32 interfaceIndex
, const nsAString
& regtype
, const nsAString
& domain
, IDNSSDBrowseListener
*listener
, IDNSSDService
**_retval NS_OUTPARAM
)
146 CDNSSDService
* service
= NULL
;
147 DNSServiceErrorType dnsErr
= 0;
154 err
= NS_ERROR_NOT_AVAILABLE
;
160 service
= new CDNSSDService( m_mainRef
, listener
);
167 if ( service
== NULL
)
169 err
= NS_ERROR_FAILURE
;
173 dnsErr
= DNSServiceBrowse( &service
->m_subRef
, kDNSServiceFlagsShareConnection
, interfaceIndex
, NS_ConvertUTF16toUTF8( regtype
).get(), NS_ConvertUTF16toUTF8( domain
).get(), ( DNSServiceBrowseReply
) BrowseReply
, service
);
175 if ( dnsErr
!= kDNSServiceErr_NoError
)
177 err
= NS_ERROR_FAILURE
;
188 if ( err
&& service
)
198 /* IDNSSDService resolve (in long interfaceIndex, in AString name, in AString regtype, in AString domain, in IDNSSDResolveListener listener); */
200 CDNSSDService::Resolve(PRInt32 interfaceIndex
, const nsAString
& name
, const nsAString
& regtype
, const nsAString
& domain
, IDNSSDResolveListener
*listener
, IDNSSDService
**_retval NS_OUTPARAM
)
202 CDNSSDService
* service
;
203 DNSServiceErrorType dnsErr
;
210 err
= NS_ERROR_NOT_AVAILABLE
;
216 service
= new CDNSSDService( m_mainRef
, listener
);
223 if ( service
== NULL
)
225 err
= NS_ERROR_FAILURE
;
229 dnsErr
= DNSServiceResolve( &service
->m_subRef
, kDNSServiceFlagsShareConnection
, interfaceIndex
, NS_ConvertUTF16toUTF8( name
).get(), NS_ConvertUTF16toUTF8( regtype
).get(), NS_ConvertUTF16toUTF8( domain
).get(), ( DNSServiceResolveReply
) ResolveReply
, service
);
231 if ( dnsErr
!= kDNSServiceErr_NoError
)
233 err
= NS_ERROR_FAILURE
;
244 if ( err
&& service
)
256 CDNSSDService::Stop()
260 DNSServiceRefDeallocate( m_subRef
);
269 CDNSSDService::Read( void * arg
)
271 NS_PRECONDITION( arg
!= NULL
, "arg is NULL" );
273 NS_DispatchToMainThread( ( CDNSSDService
* ) arg
);
280 nsresult err
= NS_OK
;
282 NS_PRECONDITION( m_mainRef
!= NULL
, "m_mainRef is NULL" );
286 if ( PR_Available( m_fileDesc
) > 0 )
288 if ( DNSServiceProcessResult( m_mainRef
) != kDNSServiceErr_NoError
)
290 err
= NS_ERROR_FAILURE
;
296 err
= SetupNotifications();
304 CDNSSDService::BrowseReply
307 DNSServiceFlags flags
,
308 uint32_t interfaceIndex
,
309 DNSServiceErrorType errorCode
,
310 const char * serviceName
,
311 const char * regtype
,
312 const char * replyDomain
,
316 CDNSSDService
* self
= ( CDNSSDService
* ) context
;
318 // This should never be NULL, but let's be defensive.
322 IDNSSDBrowseListener
* listener
= ( IDNSSDBrowseListener
* ) self
->m_listener
;
326 if ( listener
!= NULL
)
328 listener
->OnBrowse( self
, ( flags
& kDNSServiceFlagsAdd
) ? PR_TRUE
: PR_FALSE
, interfaceIndex
, errorCode
, NS_ConvertUTF8toUTF16( serviceName
), NS_ConvertUTF8toUTF16( regtype
), NS_ConvertUTF8toUTF16( replyDomain
) );
335 CDNSSDService::ResolveReply
338 DNSServiceFlags flags
,
339 uint32_t interfaceIndex
,
340 DNSServiceErrorType errorCode
,
341 const char * fullname
,
342 const char * hosttarget
,
345 const unsigned char * txtRecord
,
349 CDNSSDService
* self
= ( CDNSSDService
* ) context
;
351 // This should never be NULL, but let's be defensive.
355 IDNSSDResolveListener
* listener
= ( IDNSSDResolveListener
* ) self
->m_listener
;
359 if ( listener
!= NULL
)
361 std::string path
= "";
362 const void * value
= NULL
;
363 uint8_t valueLen
= 0;
365 value
= TXTRecordGetValuePtr( txtLen
, txtRecord
, "path", &valueLen
);
367 if ( value
&& valueLen
)
371 temp
= new char[ valueLen
+ 2 ];
377 memset( temp
, 0, valueLen
+ 2 );
379 if ( ( ( char* ) value
)[ 0 ] != '/' )
384 memcpy( dst
, value
, valueLen
);
390 listener
->OnResolve( self
, interfaceIndex
, errorCode
, NS_ConvertUTF8toUTF16( fullname
), NS_ConvertUTF8toUTF16( hosttarget
) , ntohs( port
), NS_ConvertUTF8toUTF16( path
.c_str() ) );