diff --git a/bonjour-sdk/CommonServices.h b/bonjour-sdk/CommonServices.h index b178a8d..fecfb0f 100644 --- a/bonjour-sdk/CommonServices.h +++ b/bonjour-sdk/CommonServices.h @@ -5,9 +5,9 @@ * 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. @@ -17,15 +17,15 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @header CommonServices - - Common Services for Mac OS X, Linux, Palm, VxWorks, Windows, and Windows CE. -*/ -#ifndef __COMMON_SERVICES__ -#define __COMMON_SERVICES__ + Common Services for Mac OS X, Linux, Palm, VxWorks, Windows, and Windows CE. + */ -#ifdef __cplusplus - extern "C" { +#ifndef __COMMON_SERVICES__ +#define __COMMON_SERVICES__ + +#ifdef __cplusplus +extern "C" { #endif #if 0 @@ -38,87 +38,97 @@ // Macintosh -#if( !defined( TARGET_OS_MAC ) ) - #if( ( macintosh || __MACH__ ) && !KERNEL ) - // ConditionalMacros.h in CoreServices will define this TARGET_* flag. - #else - #define TARGET_OS_MAC 0 - #endif +#if ( !defined( TARGET_OS_MAC ) ) + #if ( ( macintosh || __MACH__ ) && !KERNEL ) +// ConditionalMacros.h in CoreServices will define this TARGET_* flag. + #else + #define TARGET_OS_MAC 0 + #endif #endif -#if( !defined( TARGET_API_MAC_OSX_KERNEL ) ) - #if( __MACH__ && KERNEL ) - #define TARGET_API_MAC_OSX_KERNEL 1 - #else - #define TARGET_API_MAC_OSX_KERNEL 0 - #endif +#if ( !defined( TARGET_API_MAC_OSX_KERNEL ) ) + #if ( __MACH__ && KERNEL ) + #define TARGET_API_MAC_OSX_KERNEL 1 + #else + #define TARGET_API_MAC_OSX_KERNEL 0 + #endif +#endif + +// FreeBSD + +#if ( !defined( TARGET_OS_FREEBSD ) ) + #if ( defined( __FreeBSD__ ) ) + #define TARGET_OS_FREEBSD 1 + #else + #define TARGET_OS_FREEBSD 0 + #endif #endif // Linux -#if( !defined( TARGET_OS_LINUX ) ) - #if( defined( __linux__ ) ) - #define TARGET_OS_LINUX 1 - #else - #define TARGET_OS_LINUX 0 - #endif +#if ( !defined( TARGET_OS_LINUX ) ) + #if ( defined( __linux__ ) ) + #define TARGET_OS_LINUX 1 + #else + #define TARGET_OS_LINUX 0 + #endif #endif // Solaris -#if( !defined( TARGET_OS_SOLARIS ) ) - #if( defined(solaris) || (defined(__SVR4) && defined(sun)) ) - #define TARGET_OS_SOLARIS 1 - #else - #define TARGET_OS_SOLARIS 0 - #endif +#if ( !defined( TARGET_OS_SOLARIS ) ) + #if ( defined(solaris) || (defined(__SVR4) && defined(sun)) ) + #define TARGET_OS_SOLARIS 1 + #else + #define TARGET_OS_SOLARIS 0 + #endif #endif // Palm -#if( !defined( TARGET_OS_PALM ) ) - #if( defined( __PALMOS_TRAPS__ ) || defined( __PALMOS_ARMLET__ ) ) - #define TARGET_OS_PALM 1 - #else - #define TARGET_OS_PALM 0 - #endif +#if ( !defined( TARGET_OS_PALM ) ) + #if ( defined( __PALMOS_TRAPS__ ) || defined( __PALMOS_ARMLET__ ) ) + #define TARGET_OS_PALM 1 + #else + #define TARGET_OS_PALM 0 + #endif #endif // VxWorks -#if( !defined( TARGET_OS_VXWORKS ) ) - - // No predefined macro for VxWorks so just assume VxWorks if nothing else is set. - - #if( !macintosh && !__MACH__ && !defined( __linux__ ) && !defined ( __SVR4 ) && !defined ( __sun ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) ) - #define TARGET_OS_VXWORKS 1 - #else - #define TARGET_OS_VXWORKS 0 - #endif +#if ( !defined( TARGET_OS_VXWORKS ) ) + +// No predefined macro for VxWorks so just assume VxWorks if nothing else is set. + + #if ( !macintosh && !__MACH__ && !defined( __FreeBSD__ ) && !defined( __linux__ ) && !defined ( __SVR4 ) && !defined ( __sun ) && !defined( __PALMOS_TRAPS__ ) && !defined( __PALMOS_ARMLET__ ) && !defined( _WIN32 ) ) + #define TARGET_OS_VXWORKS 1 + #else + #define TARGET_OS_VXWORKS 0 + #endif #endif // Windows -#if( !defined( TARGET_OS_WIN32 ) ) - #if( macintosh || __MACH__ ) - // ConditionalMacros.h in CoreServices will define this TARGET_* flag. - #else - #if( defined( _WIN32 ) ) - #define TARGET_OS_WIN32 1 - #else - #define TARGET_OS_WIN32 0 - #endif - #endif +#if ( !defined( TARGET_OS_WIN32 ) ) + #if ( macintosh || __MACH__ ) +// ConditionalMacros.h in CoreServices will define this TARGET_* flag. + #else + #if ( defined( _WIN32 ) ) + #define TARGET_OS_WIN32 1 + #else + #define TARGET_OS_WIN32 0 + #endif + #endif #endif // Windows CE -#if( !defined( TARGET_OS_WINDOWS_CE ) ) - #if( defined( _WIN32_WCE ) ) - #define TARGET_OS_WINDOWS_CE 1 - #else - #define TARGET_OS_WINDOWS_CE 0 - #endif +#if ( !defined( TARGET_OS_WINDOWS_CE ) ) + #if ( defined( _WIN32_WCE ) ) + #define TARGET_OS_WINDOWS_CE 1 + #else + #define TARGET_OS_WINDOWS_CE 0 + #endif #endif #if 0 @@ -129,142 +139,151 @@ // Includes //=========================================================================================================================== -#if( !KERNEL ) - #if defined(WIN32) && !defined(_WSPIAPI_COUNTOF) - #define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) - #endif - #include +#if ( !KERNEL ) + #if defined(WIN32) && !defined(_WSPIAPI_COUNTOF) + #define _WSPIAPI_COUNTOF(_Array) (sizeof(_Array) / sizeof(_Array[0])) + #endif + #include #endif - -#if( ( macintosh || __MACH__ ) && !KERNEL ) - - #if( defined( __MWERKS__ ) ) - #if( __option( c9x ) ) - #include - #endif - #else - #include - #endif - - #include - - #if( __MACH__ ) - - // Mac OS X - - #include - #include - #include - #include - #include - #include - #include - #include - #else - - // Classic Mac OS - - #include - #include - - #endif - -#elif( KERNEL ) - - // Mac OS X Kernel - - #include - - #include - #include - -#elif( TARGET_OS_LINUX ) - - // Linux - - #include - #include - -#elif( TARGET_OS_SOLARIS ) - - // Solaris +#if ( ( macintosh || __MACH__ ) && !KERNEL ) - #include + #if ( defined( __MWERKS__ ) ) + #if ( __option( c9x ) ) + #include + #endif + #else + #include + #endif - #include - #include + #include - #if ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) ) - #define TARGET_RT_LITTLE_ENDIAN 1 - #endif - #if ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) ) - #define TARGET_RT_BIG_ENDIAN 1 - #endif + #if ( __MACH__ ) -#elif( TARGET_OS_PALM ) - - // Palm (no special includes yet). +// Mac OS X -#elif( TARGET_OS_VXWORKS ) - - // VxWorks - - #include "vxWorks.h" - -#elif( TARGET_OS_WIN32 ) - - // Windows - - #if( !defined( WIN32_WINDOWS ) ) - #define WIN32_WINDOWS 0x0401 - #endif - - #if( !defined( _WIN32_WINDOWS ) ) - #define _WIN32_WINDOWS 0x0401 - #endif - - #if( !defined( WIN32_LEAN_AND_MEAN ) ) - #define WIN32_LEAN_AND_MEAN // Needed to avoid redefinitions by Windows interfaces. - #endif - - #if( defined( __MWERKS__ ) ) - - #if( __option( c9x ) ) - #include - #endif - - #include - - #elif( defined( _MSC_VER ) ) - - #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros. - #pragma warning( disable:4706 ) // Disable "assignment within conditional expression" for Microsoft headers. - - #endif + #include + #include + #include + #include + #include + #include + #include + #include + + #else + +// Classic Mac OS + + #include + #include + + #endif + +#elif ( KERNEL ) + +// Mac OS X Kernel + + #include + + #include + #include + +#elif ( TARGET_OS_FREEBSD ) + +// FreeBSD + #include + #include + #include + #include + #include + +#elif ( TARGET_OS_LINUX ) + +// Linux + + #include + #include + +#elif ( TARGET_OS_SOLARIS ) + +// Solaris + + #include + + #include + #include + + #if ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) ) + #define TARGET_RT_LITTLE_ENDIAN 1 + #endif + #if ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) ) + #define TARGET_RT_BIG_ENDIAN 1 + #endif + +#elif ( TARGET_OS_PALM ) + +// Palm (no special includes yet). + +#elif ( TARGET_OS_VXWORKS ) + +// VxWorks + + #include "vxWorks.h" + +#elif ( TARGET_OS_WIN32 ) + +// Windows + + #if ( !defined( WIN32_WINDOWS ) ) + #define WIN32_WINDOWS 0x0401 + #endif + + #if ( !defined( _WIN32_WINDOWS ) ) + #define _WIN32_WINDOWS 0x0401 + #endif + + #if ( !defined( WIN32_LEAN_AND_MEAN ) ) + #define WIN32_LEAN_AND_MEAN // Needed to avoid redefinitions by Windows interfaces. + #endif + + #if ( defined( __MWERKS__ ) ) + + #if ( __option( c9x ) ) + #include + #endif + + #include + + #elif ( defined( _MSC_VER ) ) + + #pragma warning( disable:4127 ) // Disable "conditional expression is constant" warning for debug macros. + #pragma warning( disable:4706 ) // Disable "assignment within conditional expression" for Microsoft headers. + + #endif + + #include + #include + #include + + #if ( defined( _MSC_VER ) ) + #pragma warning( default:4706 ) + #endif - #include - #include - #include - - #if( defined( _MSC_VER ) ) - #pragma warning( default:4706 ) - #endif - #else - #error unknown OS - update this file to support your OS + #error unknown OS - update this file to support your OS #endif -#if( !defined( TARGET_BUILD_MAIN ) ) - #if( !TARGET_OS_VXWORKS ) - #define TARGET_BUILD_MAIN 1 - #endif +#if ( !defined( TARGET_BUILD_MAIN ) ) + #if ( !TARGET_OS_VXWORKS ) + #define TARGET_BUILD_MAIN 1 + #endif #endif -#if( __GNUC__ || !TARGET_OS_VXWORKS ) - #define TARGET_LANGUAGE_C_LIKE 1 +#if ( __GNUC__ || !TARGET_OS_VXWORKS ) + #define TARGET_LANGUAGE_C_LIKE 1 #else - #define TARGET_LANGUAGE_C_LIKE 0 + #define TARGET_LANGUAGE_C_LIKE 0 #endif #if 0 @@ -277,36 +296,36 @@ // PowerPC -#if( !defined( TARGET_CPU_PPC ) ) - #if( defined( __ppc__ ) || defined( __PPC__ ) || defined( powerpc ) || defined( ppc ) || defined( _M_MPPC ) ) - #define TARGET_CPU_PPC 1 - #else - #define TARGET_CPU_PPC 0 - #endif +#if ( !defined( TARGET_CPU_PPC ) ) + #if ( defined( __ppc__ ) || defined( __PPC__ ) || defined( powerpc ) || defined( ppc ) || defined( _M_MPPC ) ) + #define TARGET_CPU_PPC 1 + #else + #define TARGET_CPU_PPC 0 + #endif #endif // x86 -#if( !defined( TARGET_CPU_X86 ) ) - #if( __INTEL__ || defined( __i386__ ) || defined( i386 ) || defined( intel ) || defined( _M_IX86 ) ) - #define TARGET_CPU_X86 1 - #else - #define TARGET_CPU_X86 0 - #endif +#if ( !defined( TARGET_CPU_X86 ) ) + #if ( __INTEL__ || defined( __i386__ ) || defined( i386 ) || defined( intel ) || defined( _M_IX86 ) ) + #define TARGET_CPU_X86 1 + #else + #define TARGET_CPU_X86 0 + #endif #endif // MIPS -#if( !defined( TARGET_CPU_MIPS ) ) - #if( __MIPS__ || defined( MIPS32 ) || defined( R3000 ) || defined( R4000 ) || defined( R4650 ) || defined( _M_MRX000 ) ) - #define TARGET_CPU_MIPS 1 - #else - #define TARGET_CPU_MIPS 0 - #endif +#if ( !defined( TARGET_CPU_MIPS ) ) + #if ( __MIPS__ || defined( MIPS32 ) || defined( R3000 ) || defined( R4000 ) || defined( R4650 ) || defined( _M_MRX000 ) ) + #define TARGET_CPU_MIPS 1 + #else + #define TARGET_CPU_MIPS 0 + #endif #endif -#if( !defined( TARGET_CPU_PPC ) && !defined( TARGET_CPU_X86 ) && !defined( TARGET_CPU_MIPS ) ) - #error unknown CPU - update this file to support your CPU +#if ( !defined( TARGET_CPU_PPC ) && !defined( TARGET_CPU_X86 ) && !defined( TARGET_CPU_MIPS ) ) + #error unknown CPU - update this file to support your CPU #endif #if 0 @@ -319,68 +338,68 @@ // TARGET_RT_LITTLE_ENDIAN -#if( !defined( TARGET_RT_LITTLE_ENDIAN ) ) - #if( MIPSEL || IL_LITTLE_ENDIAN || defined( __LITTLE_ENDIAN__ ) || \ - ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) ) || \ - ( defined( _BYTE_ORDER ) && defined( _LITTLE_ENDIAN ) && ( _BYTE_ORDER == _LITTLE_ENDIAN ) ) || \ - ( defined( __BYTE_ORDER ) && defined( __LITTLE_ENDIAN ) && ( __BYTE_ORDER == __LITTLE_ENDIAN ) ) || \ - TARGET_CPU_X86 || ( defined( TARGET_RT_BIG_ENDIAN ) && !TARGET_RT_BIG_ENDIAN ) ) - #define TARGET_RT_LITTLE_ENDIAN 1 - #else - #define TARGET_RT_LITTLE_ENDIAN 0 - #endif +#if ( !defined( TARGET_RT_LITTLE_ENDIAN ) ) + #if ( MIPSEL || IL_LITTLE_ENDIAN || defined( __LITTLE_ENDIAN__ ) || \ + ( defined( BYTE_ORDER ) && defined( LITTLE_ENDIAN ) && ( BYTE_ORDER == LITTLE_ENDIAN ) ) || \ + ( defined( _BYTE_ORDER ) && defined( _LITTLE_ENDIAN ) && ( _BYTE_ORDER == _LITTLE_ENDIAN ) ) || \ + ( defined( __BYTE_ORDER ) && defined( __LITTLE_ENDIAN ) && ( __BYTE_ORDER == __LITTLE_ENDIAN ) ) || \ + TARGET_CPU_X86 || ( defined( TARGET_RT_BIG_ENDIAN ) && !TARGET_RT_BIG_ENDIAN ) ) + #define TARGET_RT_LITTLE_ENDIAN 1 + #else + #define TARGET_RT_LITTLE_ENDIAN 0 + #endif #endif // TARGET_RT_BIG_ENDIAN -#if( !defined( TARGET_RT_BIG_ENDIAN ) ) - #if( MIPSEB || IL_BIG_ENDIAN || defined( __BIG_ENDIAN__ ) || \ - ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) ) || \ - ( defined( _BYTE_ORDER ) && defined( _BIG_ENDIAN ) && ( _BYTE_ORDER == _BIG_ENDIAN ) ) || \ - ( defined( __BYTE_ORDER ) && defined( __BIG_ENDIAN ) && ( __BYTE_ORDER == __BIG_ENDIAN ) ) || \ - ( defined( TARGET_RT_LITTLE_ENDIAN ) && !TARGET_RT_LITTLE_ENDIAN ) ) - #define TARGET_RT_BIG_ENDIAN 1 - #else - #define TARGET_RT_BIG_ENDIAN 0 - #endif +#if ( !defined( TARGET_RT_BIG_ENDIAN ) ) + #if ( MIPSEB || IL_BIG_ENDIAN || defined( __BIG_ENDIAN__ ) || \ + ( defined( BYTE_ORDER ) && defined( BIG_ENDIAN ) && ( BYTE_ORDER == BIG_ENDIAN ) ) || \ + ( defined( _BYTE_ORDER ) && defined( _BIG_ENDIAN ) && ( _BYTE_ORDER == _BIG_ENDIAN ) ) || \ + ( defined( __BYTE_ORDER ) && defined( __BIG_ENDIAN ) && ( __BYTE_ORDER == __BIG_ENDIAN ) ) || \ + ( defined( TARGET_RT_LITTLE_ENDIAN ) && !TARGET_RT_LITTLE_ENDIAN ) ) + #define TARGET_RT_BIG_ENDIAN 1 + #else + #define TARGET_RT_BIG_ENDIAN 0 + #endif #endif -#if( defined( TARGET_RT_LITTLE_ENDIAN ) && !defined( TARGET_RT_BIG_ENDIAN ) ) - #if( TARGET_RT_LITTLE_ENDIAN ) - #define TARGET_RT_BIG_ENDIAN 0 - #else - #define TARGET_RT_BIG_ENDIAN 1 - #endif +#if ( defined( TARGET_RT_LITTLE_ENDIAN ) && !defined( TARGET_RT_BIG_ENDIAN ) ) + #if ( TARGET_RT_LITTLE_ENDIAN ) + #define TARGET_RT_BIG_ENDIAN 0 + #else + #define TARGET_RT_BIG_ENDIAN 1 + #endif #endif -#if( defined( TARGET_RT_BIG_ENDIAN ) && !defined( TARGET_RT_LITTLE_ENDIAN ) ) - #if( TARGET_RT_BIG_ENDIAN ) - #define TARGET_RT_LITTLE_ENDIAN 0 - #else - #define TARGET_RT_LITTLE_ENDIAN 1 - #endif +#if ( defined( TARGET_RT_BIG_ENDIAN ) && !defined( TARGET_RT_LITTLE_ENDIAN ) ) + #if ( TARGET_RT_BIG_ENDIAN ) + #define TARGET_RT_LITTLE_ENDIAN 0 + #else + #define TARGET_RT_LITTLE_ENDIAN 1 + #endif #endif -#if( !defined( TARGET_RT_LITTLE_ENDIAN ) || !defined( TARGET_RT_BIG_ENDIAN ) ) - #error unknown byte order - update this file to support your byte order +#if ( !defined( TARGET_RT_LITTLE_ENDIAN ) || !defined( TARGET_RT_BIG_ENDIAN ) ) + #error unknown byte order - update this file to support your byte order #endif // TARGET_RT_BYTE_ORDER -#if( !defined( TARGET_RT_BYTE_ORDER_BIG_ENDIAN ) ) - #define TARGET_RT_BYTE_ORDER_BIG_ENDIAN 1234 +#if ( !defined( TARGET_RT_BYTE_ORDER_BIG_ENDIAN ) ) + #define TARGET_RT_BYTE_ORDER_BIG_ENDIAN 1234 #endif -#if( !defined( TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN ) ) - #define TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN 4321 +#if ( !defined( TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN ) ) + #define TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN 4321 #endif -#if( !defined( TARGET_RT_BYTE_ORDER ) ) - #if( TARGET_RT_LITTLE_ENDIAN ) - #define TARGET_RT_BYTE_ORDER TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN - #else - #define TARGET_RT_BYTE_ORDER TARGET_RT_BYTE_ORDER_BIG_ENDIAN - #endif +#if ( !defined( TARGET_RT_BYTE_ORDER ) ) + #if ( TARGET_RT_LITTLE_ENDIAN ) + #define TARGET_RT_BYTE_ORDER TARGET_RT_BYTE_ORDER_LITTLE_ENDIAN + #else + #define TARGET_RT_BYTE_ORDER TARGET_RT_BYTE_ORDER_BIG_ENDIAN + #endif #endif #if 0 @@ -391,15 +410,15 @@ // Constants //=========================================================================================================================== -#if( !TARGET_OS_MAC ) - #define CR '\r' +#if ( !TARGET_OS_MAC ) + #define CR '\r' #endif -#define LF '\n' -#define CRSTR "\r" -#define LFSTR "\n" -#define CRLF "\r\n" -#define CRCR "\r\r" +#define LF '\n' +#define CRSTR "\r" +#define LFSTR "\n" +#define CRLF "\r\n" +#define CRCR "\r\r" #if 0 #pragma mark == Compatibility == @@ -411,135 +430,135 @@ // Macros to allow the same code to work on Windows and other sockets API-compatible platforms. -#if( TARGET_OS_WIN32 ) - #define close_compat( X ) closesocket( X ) - #define errno_compat() (int) GetLastError() - #define set_errno_compat( X ) SetLastError( X ) - #define EWOULDBLOCK_compat WSAEWOULDBLOCK - #define ETIMEDOUT_compat WSAETIMEDOUT - #define ENOTCONN_compat WSAENOTCONN - #define IsValidSocket( X ) ( ( X ) != INVALID_SOCKET ) - #define kInvalidSocketRef INVALID_SOCKET - #if( TARGET_LANGUAGE_C_LIKE ) - typedef SOCKET SocketRef; - #endif +#if ( TARGET_OS_WIN32 ) + #define close_compat( X ) closesocket( X ) + #define errno_compat() (int) GetLastError() + #define set_errno_compat( X ) SetLastError( X ) + #define EWOULDBLOCK_compat WSAEWOULDBLOCK + #define ETIMEDOUT_compat WSAETIMEDOUT + #define ENOTCONN_compat WSAENOTCONN + #define IsValidSocket( X ) ( ( X ) != INVALID_SOCKET ) + #define kInvalidSocketRef INVALID_SOCKET + #if ( TARGET_LANGUAGE_C_LIKE ) +typedef SOCKET SocketRef; + #endif #else - #define close_compat( X ) close( X ) - #define errno_compat() errno - #define set_errno_compat( X ) do { errno = ( X ); } while( 0 ) - #define EWOULDBLOCK_compat EWOULDBLOCK - #define ETIMEDOUT_compat ETIMEDOUT - #define ENOTCONN_compat ENOTCONN - #define IsValidSocket( X ) ( ( X ) >= 0 ) - #define kInvalidSocketRef -1 - #if( TARGET_LANGUAGE_C_LIKE ) - typedef int SocketRef; - #endif + #define close_compat( X ) close( X ) + #define errno_compat() errno + #define set_errno_compat( X ) do { errno = ( X ); } while( 0 ) + #define EWOULDBLOCK_compat EWOULDBLOCK + #define ETIMEDOUT_compat ETIMEDOUT + #define ENOTCONN_compat ENOTCONN + #define IsValidSocket( X ) ( ( X ) >= 0 ) + #define kInvalidSocketRef -1 + #if ( TARGET_LANGUAGE_C_LIKE ) +typedef int SocketRef; + #endif #endif // socklen_t is not defined on the following platforms so emulate it if not defined: -// +// // - Pre-Panther Mac OS X. Panther defines SO_NOADDRERR so trigger off that. // - Windows SDK prior to 2003. 2003+ SDK's define EAI_AGAIN so trigger off that. // - VxWorks -#if( TARGET_LANGUAGE_C_LIKE ) - #if( ( TARGET_OS_MAC && !defined( SO_NOADDRERR ) ) || ( TARGET_OS_WIN32 && !defined( EAI_AGAIN ) ) || TARGET_OS_VXWORKS ) - typedef int socklen_t; - #endif +#if ( TARGET_LANGUAGE_C_LIKE ) + #if ( ( TARGET_OS_MAC && !defined( SO_NOADDRERR ) ) || ( TARGET_OS_WIN32 && !defined( EAI_AGAIN ) ) || TARGET_OS_VXWORKS ) +typedef int socklen_t; + #endif #endif // ssize_t is not defined on the following platforms so emulate it if not defined: -// +// // - Mac OS X when not building with BSD headers // - Windows -#if( TARGET_LANGUAGE_C_LIKE ) - #if( !defined(_SSIZE_T) && ( TARGET_OS_WIN32 || !defined( _BSD_SSIZE_T_DEFINED_ ) ) && !TARGET_OS_LINUX && !TARGET_OS_VXWORKS && !TARGET_OS_MAC) - typedef int ssize_t; - #endif +#if ( TARGET_LANGUAGE_C_LIKE ) + #if ( !defined(_SSIZE_T) && ( TARGET_OS_WIN32 || !defined( _BSD_SSIZE_T_DEFINED_ ) ) && !TARGET_OS_FREEBSD && !TARGET_OS_LINUX && !TARGET_OS_VXWORKS && !TARGET_OS_MAC) +typedef int ssize_t; + #endif #endif // sockaddr_storage is not supported on non-IPv6 machines so alias it to an IPv4-compatible structure. -#if( TARGET_LANGUAGE_C_LIKE ) - #if( !defined( AF_INET6 ) ) - #define sockaddr_storage sockaddr_in - #define ss_family sin_family - #endif +#if ( TARGET_LANGUAGE_C_LIKE ) + #if ( !defined( AF_INET6 ) ) + #define sockaddr_storage sockaddr_in + #define ss_family sin_family + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined SOCKADDR_IS_IP_LOOPBACK - - @abstract Determines if a sockaddr is an IPv4 or IPv6 loopback address (if IPv6 is supported). -*/ -#if( defined( AF_INET6 ) ) - #define SOCKADDR_IS_IP_LOOPBACK( SA ) \ - ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ - ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \ - : ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET6 ) \ - ? IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) \ - : 0 + @abstract Determines if a sockaddr is an IPv4 or IPv6 loopback address (if IPv6 is supported). + */ + +#if ( defined( AF_INET6 ) ) + #define SOCKADDR_IS_IP_LOOPBACK( SA ) \ + ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \ + : ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET6 ) \ + ? IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) \ + : 0 #else - #define SOCKADDR_IS_IP_LOOPBACK( SA ) \ - ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ - ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \ - : 0 + #define SOCKADDR_IS_IP_LOOPBACK( SA ) \ + ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( (const struct sockaddr_in *)( SA ) )->sin_addr.s_addr == htonl( INADDR_LOOPBACK ) ) \ + : 0 #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined SOCKADDR_IS_IP_LINK_LOCAL - - @abstract Determines if a sockaddr is an IPv4 or IPv6 link-local address (if IPv6 is supported). -*/ -#if( defined( AF_INET6 ) ) - #define SOCKADDR_IS_IP_LINK_LOCAL( SA ) \ - ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ - ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) && \ - ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) ) \ - : IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) ) + @abstract Determines if a sockaddr is an IPv4 or IPv6 link-local address (if IPv6 is supported). + */ + +#if ( defined( AF_INET6 ) ) + #define SOCKADDR_IS_IP_LINK_LOCAL( SA ) \ + ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) && \ + ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) ) \ + : IN6_IS_ADDR_LOOPBACK( &( (const struct sockaddr_in6 *)( SA ) )->sin6_addr ) ) #else - #define SOCKADDR_IS_IP_LINK_LOCAL( SA ) \ - ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ - ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) && \ - ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) ) \ - : 0 ) + #define SOCKADDR_IS_IP_LINK_LOCAL( SA ) \ + ( ( ( (const struct sockaddr *)( SA ) )->sa_family == AF_INET ) \ + ? ( ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 0 ] == 169 ) && \ + ( ( (uint8_t *)( &( (const struct sockaddr_in *)( SA ) )->sin_addr ) )[ 1 ] == 254 ) ) \ + : 0 ) #endif -// _beginthreadex and _endthreadex are not supported on Windows CE 2.1 or later (the C runtime issues with leaking -// resources have apparently been resolved and they seem to have just ripped out support for the API) so map it to +// _beginthreadex and _endthreadex are not supported on Windows CE 2.1 or later (the C runtime issues with leaking +// resources have apparently been resolved and they seem to have just ripped out support for the API) so map it to // CreateThread on Windows CE. -#if( TARGET_OS_WINDOWS_CE ) - #define _beginthreadex_compat( SECURITY_PTR, STACK_SIZE, START_ADDRESS, ARG_LIST, FLAGS, THREAD_ID_PTR ) \ - (uintptr_t) CreateThread( SECURITY_PTR, STACK_SIZE, (LPTHREAD_START_ROUTINE) START_ADDRESS, ARG_LIST, FLAGS, \ - (LPDWORD) THREAD_ID_PTR ) - - #define _endthreadex_compat( RESULT ) ExitThread( (DWORD) RESULT ) -#elif( TARGET_OS_WIN32 ) - #define _beginthreadex_compat _beginthreadex - #define _endthreadex_compat _endthreadex +#if ( TARGET_OS_WINDOWS_CE ) + #define _beginthreadex_compat( SECURITY_PTR, STACK_SIZE, START_ADDRESS, ARG_LIST, FLAGS, THREAD_ID_PTR ) \ + (uintptr_t) CreateThread( SECURITY_PTR, STACK_SIZE, (LPTHREAD_START_ROUTINE) START_ADDRESS, ARG_LIST, FLAGS, \ + (LPDWORD) THREAD_ID_PTR ) + + #define _endthreadex_compat( RESULT ) ExitThread( (DWORD) RESULT ) +#elif ( TARGET_OS_WIN32 ) + #define _beginthreadex_compat _beginthreadex + #define _endthreadex_compat _endthreadex #endif // The C99 "inline" keyword is not supported by Microsoft compilers, but they do support __inline so map it when needed. -#if( defined( _MSC_VER ) ) - #define inline_compat __inline +#if ( defined( _MSC_VER ) ) + #define inline_compat __inline #else - #define inline_compat inline + #define inline_compat inline #endif -// Calling conventions +// Calling conventions -#if( !defined( CALLBACK_COMPAT ) ) - #if( TARGET_OS_WIN32 || TARGET_OS_WINDOWS_CE ) - #define CALLBACK_COMPAT CALLBACK - #else - #define CALLBACK_COMPAT - #endif +#if ( !defined( CALLBACK_COMPAT ) ) + #if ( TARGET_OS_WIN32 || TARGET_OS_WINDOWS_CE ) + #define CALLBACK_COMPAT CALLBACK + #else + #define CALLBACK_COMPAT + #endif #endif #if 0 @@ -549,270 +568,276 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @defined kSizeCString - @abstract A meta-value to pass to supported routines to indicate the size should be calculated with strlen. -*/ + @abstract A meta-value to pass to supported routines to indicate the size should be calculated with strlen. + */ -#define kSizeCString ( (size_t) -1 ) +#define kSizeCString ( (size_t) -1 ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined sizeof_array - - @abstract Determines the number of elements in an array. -*/ -#define sizeof_array( X ) ( sizeof( X ) / sizeof( X[ 0 ] ) ) + @abstract Determines the number of elements in an array. + */ + +#define sizeof_array( X ) ( sizeof( X ) / sizeof( X[ 0 ] ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined sizeof_element - - @abstract Determines the size of an array element. -*/ -#define sizeof_element( X ) sizeof( X[ 0 ] ) + @abstract Determines the size of an array element. + */ + +#define sizeof_element( X ) sizeof( X[ 0 ] ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined sizeof_string - - @abstract Determines the size of a constant C string, excluding the null terminator. -*/ -#define sizeof_string( X ) ( sizeof( ( X ) ) - 1 ) + @abstract Determines the size of a constant C string, excluding the null terminator. + */ + +#define sizeof_string( X ) ( sizeof( ( X ) ) - 1 ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined sizeof_field - - @abstract Determines the size of a field of a type. -*/ -#define sizeof_field( TYPE, FIELD ) sizeof( ( ( (TYPE *) 0 )->FIELD ) ) + @abstract Determines the size of a field of a type. + */ + +#define sizeof_field( TYPE, FIELD ) sizeof( ( ( (TYPE *) 0 )->FIELD ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function RoundUp - @abstract Rounds X up to a multiple of Y. -*/ + @abstract Rounds X up to a multiple of Y. + */ -#define RoundUp( X, Y ) ( ( X ) + ( ( Y ) - ( ( X ) % ( Y ) ) ) ) +#define RoundUp( X, Y ) ( ( X ) + ( ( Y ) -( ( X ) % ( Y ) ) ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function IsAligned - @abstract Returns non-zero if X is aligned to a Y byte boundary and 0 if not. Y must be a power of 2. -*/ + @abstract Returns non-zero if X is aligned to a Y byte boundary and 0 if not. Y must be a power of 2. + */ -#define IsAligned( X, Y ) ( ( ( X ) & ( ( Y ) - 1 ) ) == 0 ) +#define IsAligned( X, Y ) ( ( ( X ) &( ( Y ) -1 ) ) == 0 ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function IsFieldAligned - @abstract Returns non-zero if FIELD of type TYPE is aligned to a Y byte boundary and 0 if not. Y must be a power of 2. -*/ + @abstract Returns non-zero if FIELD of type TYPE is aligned to a Y byte boundary and 0 if not. Y must be a power of 2. + */ -#define IsFieldAligned( X, TYPE, FIELD, Y ) IsAligned( ( (uintptr_t)( X ) ) + offsetof( TYPE, FIELD ), ( Y ) ) +#define IsFieldAligned( X, TYPE, FIELD, Y ) IsAligned( ( (uintptr_t)( X ) ) + offsetof( TYPE, FIELD ), ( Y ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function AlignDown - @abstract Aligns X down to a Y byte boundary. Y must be a power of 2. -*/ + @abstract Aligns X down to a Y byte boundary. Y must be a power of 2. + */ -#define AlignDown( X, Y ) ( ( X ) & ~( ( Y ) - 1 ) ) +#define AlignDown( X, Y ) ( ( X ) &~( ( Y ) -1 ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function AlignUp - @abstract Aligns X up to a Y byte boundary. Y must be a power of 2. -*/ + @abstract Aligns X up to a Y byte boundary. Y must be a power of 2. + */ -#define AlignUp( X, Y ) ( ( ( X ) + ( ( Y ) - 1 ) ) & ~( ( Y ) - 1 ) ) +#define AlignUp( X, Y ) ( ( ( X ) + ( ( Y ) -1 ) ) & ~( ( Y ) -1 ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function Min - @abstract Returns the lesser of X and Y. -*/ + @abstract Returns the lesser of X and Y. + */ -#if( !defined( Min ) ) - #define Min( X, Y ) ( ( ( X ) < ( Y ) ) ? ( X ) : ( Y ) ) +#if ( !defined( Min ) ) + #define Min( X, Y ) ( ( ( X ) < ( Y ) ) ? ( X ) : ( Y ) ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function Max - @abstract Returns the greater of X and Y. -*/ + @abstract Returns the greater of X and Y. + */ -#if( !defined( Max ) ) - #define Max( X, Y ) ( ( ( X ) > ( Y ) ) ? ( X ) : ( Y ) ) +#if ( !defined( Max ) ) + #define Max( X, Y ) ( ( ( X ) > ( Y ) ) ? ( X ) : ( Y ) ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function InsertBits - @abstract Inserts BITS (both 0 and 1 bits) into X, controlled by MASK and SHIFT, and returns the result. - - @discussion - - MASK is the bitmask of the bits in the final position. - SHIFT is the number of bits to shift left for 1 to reach the first bit position of MASK. - - For example, if you wanted to insert 0x3 into the leftmost 4 bits of a 32-bit value: - - InsertBits( 0, 0x3, 0xF0000000U, 28 ) == 0x30000000 -*/ + @abstract Inserts BITS (both 0 and 1 bits) into X, controlled by MASK and SHIFT, and returns the result. -#define InsertBits( X, BITS, MASK, SHIFT ) ( ( ( X ) & ~( MASK ) ) | ( ( ( BITS ) << ( SHIFT ) ) & ( MASK ) ) ) + @discussion + + MASK is the bitmask of the bits in the final position. + SHIFT is the number of bits to shift left for 1 to reach the first bit position of MASK. + + For example, if you wanted to insert 0x3 into the leftmost 4 bits of a 32-bit value: + + InsertBits( 0, 0x3, 0xF0000000U, 28 ) == 0x30000000 + */ + +#define InsertBits( X, BITS, MASK, SHIFT ) ( ( ( X ) &~( MASK ) ) | ( ( ( BITS ) << ( SHIFT ) ) & ( MASK ) ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function ExtractBits - @abstract Extracts bits from X, controlled by MASK and SHIFT, and returns the result. - - @discussion - - MASK is the bitmask of the bits in the final position. - SHIFT is the number of bits to shift right to right justify MASK. - - For example, if you had a 32-bit value (e.g. 0x30000000) wanted the left-most 4 bits (e.g. 3 in this example): - - ExtractBits( 0x30000000U, 0xF0000000U, 28 ) == 0x3 -*/ + @abstract Extracts bits from X, controlled by MASK and SHIFT, and returns the result. -#define ExtractBits( X, MASK, SHIFT ) ( ( ( X ) >> ( SHIFT ) ) & ( ( MASK ) >> ( SHIFT ) ) ) + @discussion + + MASK is the bitmask of the bits in the final position. + SHIFT is the number of bits to shift right to right justify MASK. + + For example, if you had a 32-bit value (e.g. 0x30000000) wanted the left-most 4 bits (e.g. 3 in this example): + + ExtractBits( 0x30000000U, 0xF0000000U, 28 ) == 0x3 + */ + +#define ExtractBits( X, MASK, SHIFT ) ( ( ( X ) >> ( SHIFT ) ) & ( ( MASK ) >> ( SHIFT ) ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function Stringify - @abstract Stringify's an expression. - - @discussion - - Stringify macros to process raw text passed via -D options to C string constants. The double-wrapping is necessary - because the C preprocessor doesn't perform its normal argument expansion pre-scan with stringified macros so the - -D macro needs to be expanded once via the wrapper macro then stringified so the raw text is stringified. Otherwise, - the replacement value would be used instead of the symbolic name (only for preprocessor symbols like #defines). - - For example: - - #define kMyConstant 1 - - printf( "%s", Stringify( kMyConstant ) ); // Prints "kMyConstant" - printf( "%s", StringifyExpansion( kMyConstant ) ); // Prints "1" - - Non-preprocessor symbols do not have this issue. For example: - - enum - { - kMyConstant = 1 - }; - - printf( "%s", Stringify( kMyConstant ) ); // Prints "kMyConstant" - printf( "%s", StringifyExpansion( kMyConstant ) ); // Prints "kMyConstant" - - See for more info on C preprocessor pre-scanning. -*/ + @abstract Stringify's an expression. -#define Stringify( X ) # X -#define StringifyExpansion( X ) Stringify( X ) + @discussion + + Stringify macros to process raw text passed via -D options to C string constants. The double-wrapping is necessary + because the C preprocessor doesn't perform its normal argument expansion pre-scan with stringified macros so the + -D macro needs to be expanded once via the wrapper macro then stringified so the raw text is stringified. Otherwise, + the replacement value would be used instead of the symbolic name (only for preprocessor symbols like #defines). + + For example: + + #define kMyConstant 1 + + printf( "%s", Stringify( kMyConstant ) ); // Prints "kMyConstant" + printf( "%s", StringifyExpansion( kMyConstant ) ); // Prints "1" + + Non-preprocessor symbols do not have this issue. For example: + + enum + { + kMyConstant = 1 + }; + + printf( "%s", Stringify( kMyConstant ) ); // Prints "kMyConstant" + printf( "%s", StringifyExpansion( kMyConstant ) ); // Prints "kMyConstant" + + See for more info on C preprocessor pre-scanning. + */ + +#define Stringify( X ) # X +#define StringifyExpansion( X ) Stringify( X ) #if 0 #pragma mark == Types == #endif -#if( TARGET_LANGUAGE_C_LIKE ) +#if ( TARGET_LANGUAGE_C_LIKE ) //=========================================================================================================================== // Standard Types //=========================================================================================================================== -#if( !defined( INT8_MIN ) ) - - #define INT8_MIN SCHAR_MIN - - #if( defined( _MSC_VER ) || defined(__MINGW32__) ) +#if ( !defined( INT8_MIN ) ) - // C99 stdint.h not supported in VC++/VS.NET yet. + #define INT8_MIN SCHAR_MIN - typedef INT8 int8_t; - typedef UINT8 uint8_t; - typedef INT16 int16_t; - typedef UINT16 uint16_t; - typedef INT32 int32_t; - typedef UINT32 uint32_t; - typedef __int64 int64_t; - typedef unsigned __int64 uint64_t; - - #elif( TARGET_OS_VXWORKS && ( TORNADO_VERSION < 220 ) ) - typedef long long int64_t; - typedef unsigned long long uint64_t; - #endif - - typedef int8_t int_least8_t; - typedef int16_t int_least16_t; - typedef int32_t int_least32_t; - typedef int64_t int_least64_t; + #if ( defined( _MSC_VER ) ) - typedef uint8_t uint_least8_t; - typedef uint16_t uint_least16_t; - typedef uint32_t uint_least32_t; - typedef uint64_t uint_least64_t; - - typedef int8_t int_fast8_t; - typedef int16_t int_fast16_t; - typedef int32_t int_fast32_t; - typedef int64_t int_fast64_t; - - typedef uint8_t uint_fast8_t; - typedef uint16_t uint_fast16_t; - typedef uint32_t uint_fast32_t; - typedef uint64_t uint_fast64_t; +// C99 stdint.h not supported in VC++/VS.NET yet. - #if( !( defined( _MSC_VER ) || defined(__MINGW32__)) || TARGET_OS_WINDOWS_CE ) - typedef long int intptr_t; - typedef unsigned long int uintptr_t; - #endif +typedef INT8 int8_t; +typedef UINT8 uint8_t; +typedef INT16 int16_t; +typedef UINT16 uint16_t; +typedef INT32 int32_t; +typedef UINT32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + + #elif ( TARGET_OS_VXWORKS && ( TORNADO_VERSION < 220 ) ) +typedef long long int64_t; +typedef unsigned long long uint64_t; + #endif + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; + +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + + #if ( !defined( _MSC_VER ) || TARGET_OS_WINDOWS_CE ) +typedef long int intptr_t; +typedef unsigned long int uintptr_t; + #endif #endif // Macros for minimum-width integer constants -#if( !defined( INT8_C ) ) - #define INT8_C( value ) value +#if ( !defined( INT8_C ) ) + #define INT8_C( value ) value #endif -#if( !defined( INT16_C ) ) - #define INT16_C( value ) value +#if ( !defined( INT16_C ) ) + #define INT16_C( value ) value #endif -#if( !defined( INT32_C ) ) - #define INT32_C( value ) value ## L +#if ( !defined( INT32_C ) ) + #define INT32_C( value ) value ## L #endif -#if( !defined( INT64_C ) ) - #if( defined( _MSC_VER ) ) - #define INT64_C( value ) value ## i64 - #else - #define INT64_C( value ) value ## LL - #endif +#if ( !defined( INT64_C ) ) + #if ( defined( _MSC_VER ) ) + #define INT64_C( value ) value ## i64 + #else + #define INT64_C( value ) value ## LL + #endif #endif -#if( !defined( UINT8_C ) ) - #define UINT8_C( value ) value ## U +#if ( !defined( UINT8_C ) ) + #define UINT8_C( value ) value ## U #endif -#if( !defined( UINT16_C ) ) - #define UINT16_C( value ) value ## U +#if ( !defined( UINT16_C ) ) + #define UINT16_C( value ) value ## U #endif -#if( !defined( UINT32_C ) ) - #define UINT32_C( value ) value ## UL +#if ( !defined( UINT32_C ) ) + #define UINT32_C( value ) value ## UL #endif -#if( !defined( UINT64_C ) ) - #if( defined( _MSC_VER ) ) - #define UINT64_C( value ) value ## UI64 - #else - #define UINT64_C( value ) value ## ULL - #endif +#if ( !defined( UINT64_C ) ) + #if ( defined( _MSC_VER ) ) + #define UINT64_C( value ) value ## UI64 + #else + #define UINT64_C( value ) value ## ULL + #endif +#endif + +// Limits + +#if( !defined( UINT32_MAX ) ) + #define UINT32_MAX UINT32_C( 4294967295 ) #endif #if 0 @@ -826,102 +851,106 @@ // C++ defines bool, true, and false. Metrowerks allows this to be controlled by the "bool" option though. // C99 defines __bool_true_false_are_defined when bool, true, and false are defined. // MacTypes.h defines true and false (Mac builds only). -// -// Note: The Metrowerks has to be in its own block because Microsoft Visual Studio .NET does not completely +// +// Note: The Metrowerks has to be in its own block because Microsoft Visual Studio .NET does not completely // short-circuit and gets confused by the option( bool ) portion of the conditional. -#if( defined( __MWERKS__ ) ) - - // Note: The following test is done on separate lines because CodeWarrior doesn't like it all on one line. - - #if( !__bool_true_false_are_defined && ( !defined( __cplusplus ) || !__option( bool ) ) ) - #define COMMON_SERVICES_NEEDS_BOOL 1 - #else - #define COMMON_SERVICES_NEEDS_BOOL 0 - #endif - - // Workaround when building with CodeWarrior, but using the Apple stdbool.h header, which uses _Bool. - - #if( __bool_true_false_are_defined && !defined( __cplusplus ) && !__option( c9x ) ) - #define _Bool int - #endif - - // Workaround when building with CodeWarrior for C++ with bool disabled and using the Apple stdbool.h header, - // which defines true and false to map to C++ true and false (which are not enabled). Serenity Now! - - #if( __bool_true_false_are_defined && defined( __cplusplus ) && !__option( bool ) ) - #define true 1 - #define false 0 - #endif +#if ( defined( __MWERKS__ ) ) + +// Note: The following test is done on separate lines because CodeWarrior doesn't like it all on one line. + + #if ( !__bool_true_false_are_defined && ( !defined( __cplusplus ) || !__option( bool ) ) ) + #define COMMON_SERVICES_NEEDS_BOOL 1 + #else + #define COMMON_SERVICES_NEEDS_BOOL 0 + #endif + +// Workaround when building with CodeWarrior, but using the Apple stdbool.h header, which uses _Bool. + + #if ( __bool_true_false_are_defined && !defined( __cplusplus ) && !__option( c9x ) ) + #define _Bool int + #endif + +// Workaround when building with CodeWarrior for C++ with bool disabled and using the Apple stdbool.h header, +// which defines true and false to map to C++ true and false (which are not enabled). Serenity Now! + + #if ( __bool_true_false_are_defined && defined( __cplusplus ) && !__option( bool ) ) + #define true 1 + #define false 0 + #endif #else - #define COMMON_SERVICES_NEEDS_BOOL ( !defined( __cplusplus ) && !__bool_true_false_are_defined ) + #if ( !defined( __cplusplus ) && !__bool_true_false_are_defined ) + #define COMMON_SERVICES_NEEDS_BOOL 1 + #else + #define COMMON_SERVICES_NEEDS_BOOL 0 + #endif #endif -#if( COMMON_SERVICES_NEEDS_BOOL ) - - typedef int bool; - - #define bool bool - - #if( !defined( __MACTYPES__ ) && !defined( true ) && !defined( false ) ) - #define true 1 - #define false 0 - #endif - - #define __bool_true_false_are_defined 1 +#if ( COMMON_SERVICES_NEEDS_BOOL ) + +typedef int bool; + + #define bool bool + + #if ( !defined( __MACTYPES__ ) && !defined( true ) && !defined( false ) ) + #define true 1 + #define false 0 + #endif + + #define __bool_true_false_are_defined 1 #endif // IOKit IOTypes.h typedef's bool if TYPE_BOOL is not defined so define it here to prevent redefinition by IOTypes.h. -#if( TARGET_API_MAC_OSX_KERNEL ) - #define TYPE_BOOL 1 +#if ( TARGET_API_MAC_OSX_KERNEL ) + #define TYPE_BOOL 1 #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef CStr255 - - @abstract 255 character null-terminated (C-style) string. -*/ -#if( TARGET_LANGUAGE_C_LIKE ) - typedef char CStr255[ 256 ]; + @abstract 255 character null-terminated (C-style) string. + */ + +#if ( TARGET_LANGUAGE_C_LIKE ) +typedef char CStr255[ 256 ]; #endif -#endif // TARGET_LANGUAGE_C_LIKE +#endif // TARGET_LANGUAGE_C_LIKE //--------------------------------------------------------------------------------------------------------------------------- /*! @defined TYPE_LONGLONG_NATIVE - @abstract Defines whether long long (or its equivalent) is natively supported or requires special libraries. -*/ + @abstract Defines whether long long (or its equivalent) is natively supported or requires special libraries. + */ -#if( !defined( TYPE_LONGLONG_NATIVE ) ) - #if( !TARGET_OS_VXWORKS ) - #define TYPE_LONGLONG_NATIVE 1 - #else - #define TYPE_LONGLONG_NATIVE 0 - #endif +#if ( !defined( TYPE_LONGLONG_NATIVE ) ) + #if ( !TARGET_OS_VXWORKS ) + #define TYPE_LONGLONG_NATIVE 1 + #else + #define TYPE_LONGLONG_NATIVE 0 + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined long_long_compat - @abstract Compatibility type to map to the closest thing to long long and unsigned long long. - - @discussion - - Neither long long nor unsigned long long are supported by Microsoft compilers, but they do support proprietary - "__int64" and "unsigned __int64" equivalents so map to those types if the real long long is not supported. -*/ + @abstract Compatibility type to map to the closest thing to long long and unsigned long long. -#if( TARGET_LANGUAGE_C_LIKE ) - #if( TARGET_OS_WIN32 ) - typedef __int64 long_long_compat; - typedef unsigned __int64 unsigned_long_long_compat; - #else - typedef signed long long long_long_compat; - typedef unsigned long long unsigned_long_long_compat; - #endif + @discussion + + Neither long long nor unsigned long long are supported by Microsoft compilers, but they do support proprietary + "__int64" and "unsigned __int64" equivalents so map to those types if the real long long is not supported. + */ + +#if ( TARGET_LANGUAGE_C_LIKE ) + #if ( TARGET_OS_WIN32 ) +typedef __int64 long_long_compat; +typedef unsigned __int64 unsigned_long_long_compat; + #else +typedef signed long long long_long_compat; +typedef unsigned long long unsigned_long_long_compat; + #endif #endif #if 0 @@ -931,155 +960,155 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @enum OSStatus - @abstract Status Code - - @constant kNoErr 0 No error occurred. - @constant kInProgressErr 1 Operation in progress. - @constant kUnknownErr -6700 Unknown error occurred. - @constant kOptionErr -6701 Option was not acceptable. - @constant kSelectorErr -6702 Selector passed in is invalid or unknown. - @constant kExecutionStateErr -6703 Call made in the wrong execution state (e.g. called at interrupt time). - @constant kPathErr -6704 Path is invalid, too long, or otherwise not usable. - @constant kParamErr -6705 Parameter is incorrect, missing, or not appropriate. - @constant kParamCountErr -6706 Incorrect or unsupported number of parameters. - @constant kCommandErr -6707 Command invalid or not supported. - @constant kIDErr -6708 Unknown, invalid, or inappropriate identifier. - @constant kStateErr -6709 Not in appropriate state to perform operation. - @constant kRangeErr -6710 Index is out of range or not valid. - @constant kRequestErr -6711 Request was improperly formed or not appropriate. - @constant kResponseErr -6712 Response was incorrect or out of sequence. - @constant kChecksumErr -6713 Checksum does not match the actual data. - @constant kNotHandledErr -6714 Operation was not handled (or not handled completely). - @constant kVersionErr -6715 Version is not incorrect or not compatibile. - @constant kSignatureErr -6716 Signature did not match what was expected. - @constant kFormatErr -6717 Unknown, invalid, or inappropriate file/data format. - @constant kNotInitializedErr -6718 Action request before needed services were initialized. - @constant kAlreadyInitializedErr -6719 Attempt made to initialize when already initialized. - @constant kNotInUseErr -6720 Object not in use (e.g. cannot abort if not already in use). - @constant kInUseErr -6721 Object is in use (e.g. cannot reuse active param blocks). - @constant kTimeoutErr -6722 Timeout occurred. - @constant kCanceledErr -6723 Operation canceled (successful cancel). - @constant kAlreadyCanceledErr -6724 Operation has already been canceled. - @constant kCannotCancelErr -6725 Operation could not be canceled (maybe already done or invalid). - @constant kDeletedErr -6726 Object has already been deleted. - @constant kNotFoundErr -6727 Something was not found. - @constant kNoMemoryErr -6728 Not enough memory was available to perform the operation. - @constant kNoResourcesErr -6729 Resources unavailable to perform the operation. - @constant kDuplicateErr -6730 Duplicate found or something is a duplicate. - @constant kImmutableErr -6731 Entity is not changeable. - @constant kUnsupportedDataErr -6732 Data is unknown or not supported. - @constant kIntegrityErr -6733 Data is corrupt. - @constant kIncompatibleErr -6734 Data is not compatible or it is in an incompatible format. - @constant kUnsupportedErr -6735 Feature or option is not supported. - @constant kUnexpectedErr -6736 Error occurred that was not expected. - @constant kValueErr -6737 Value is not appropriate. - @constant kNotReadableErr -6738 Could not read or reading is not allowed. - @constant kNotWritableErr -6739 Could not write or writing is not allowed. - @constant kBadReferenceErr -6740 An invalid or inappropriate reference was specified. - @constant kFlagErr -6741 An invalid, inappropriate, or unsupported flag was specified. - @constant kMalformedErr -6742 Something was not formed correctly. - @constant kSizeErr -6743 Size was too big, too small, or not appropriate. - @constant kNameErr -6744 Name was not correct, allowed, or appropriate. - @constant kNotReadyErr -6745 Device or service is not ready. - @constant kReadErr -6746 Could not read. - @constant kWriteErr -6747 Could not write. - @constant kMismatchErr -6748 Something does not match. - @constant kDateErr -6749 Date is invalid or out-of-range. - @constant kUnderrunErr -6750 Less data than expected. - @constant kOverrunErr -6751 More data than expected. - @constant kEndingErr -6752 Connection, session, or something is ending. - @constant kConnectionErr -6753 Connection failed or could not be established. - @constant kAuthenticationErr -6754 Authentication failed or is not supported. - @constant kOpenErr -6755 Could not open file, pipe, device, etc. - @constant kTypeErr -6756 Incorrect or incompatible type (e.g. file, data, etc.). - @constant kSkipErr -6757 Items should be or was skipped. - @constant kNoAckErr -6758 No acknowledge. - @constant kCollisionErr -6759 Collision occurred (e.g. two on bus at same time). - @constant kBackoffErr -6760 Backoff in progress and operation intentionally failed. - @constant kNoAddressAckErr -6761 No acknowledge of address. - @constant kBusyErr -6762 Cannot perform because something is busy. - @constant kNoSpaceErr -6763 Not enough space to perform operation. -*/ + @abstract Status Code -#if( TARGET_LANGUAGE_C_LIKE ) - #if( !TARGET_OS_MAC && !TARGET_API_MAC_OSX_KERNEL ) - typedef int32_t OSStatus; - #endif + @constant kNoErr 0 No error occurred. + @constant kInProgressErr 1 Operation in progress. + @constant kUnknownErr -6700 Unknown error occurred. + @constant kOptionErr -6701 Option was not acceptable. + @constant kSelectorErr -6702 Selector passed in is invalid or unknown. + @constant kExecutionStateErr -6703 Call made in the wrong execution state (e.g. called at interrupt time). + @constant kPathErr -6704 Path is invalid, too long, or otherwise not usable. + @constant kParamErr -6705 Parameter is incorrect, missing, or not appropriate. + @constant kParamCountErr -6706 Incorrect or unsupported number of parameters. + @constant kCommandErr -6707 Command invalid or not supported. + @constant kIDErr -6708 Unknown, invalid, or inappropriate identifier. + @constant kStateErr -6709 Not in appropriate state to perform operation. + @constant kRangeErr -6710 Index is out of range or not valid. + @constant kRequestErr -6711 Request was improperly formed or not appropriate. + @constant kResponseErr -6712 Response was incorrect or out of sequence. + @constant kChecksumErr -6713 Checksum does not match the actual data. + @constant kNotHandledErr -6714 Operation was not handled (or not handled completely). + @constant kVersionErr -6715 Version is not incorrect or not compatibile. + @constant kSignatureErr -6716 Signature did not match what was expected. + @constant kFormatErr -6717 Unknown, invalid, or inappropriate file/data format. + @constant kNotInitializedErr -6718 Action request before needed services were initialized. + @constant kAlreadyInitializedErr -6719 Attempt made to initialize when already initialized. + @constant kNotInUseErr -6720 Object not in use (e.g. cannot abort if not already in use). + @constant kInUseErr -6721 Object is in use (e.g. cannot reuse active param blocks). + @constant kTimeoutErr -6722 Timeout occurred. + @constant kCanceledErr -6723 Operation canceled (successful cancel). + @constant kAlreadyCanceledErr -6724 Operation has already been canceled. + @constant kCannotCancelErr -6725 Operation could not be canceled (maybe already done or invalid). + @constant kDeletedErr -6726 Object has already been deleted. + @constant kNotFoundErr -6727 Something was not found. + @constant kNoMemoryErr -6728 Not enough memory was available to perform the operation. + @constant kNoResourcesErr -6729 Resources unavailable to perform the operation. + @constant kDuplicateErr -6730 Duplicate found or something is a duplicate. + @constant kImmutableErr -6731 Entity is not changeable. + @constant kUnsupportedDataErr -6732 Data is unknown or not supported. + @constant kIntegrityErr -6733 Data is corrupt. + @constant kIncompatibleErr -6734 Data is not compatible or it is in an incompatible format. + @constant kUnsupportedErr -6735 Feature or option is not supported. + @constant kUnexpectedErr -6736 Error occurred that was not expected. + @constant kValueErr -6737 Value is not appropriate. + @constant kNotReadableErr -6738 Could not read or reading is not allowed. + @constant kNotWritableErr -6739 Could not write or writing is not allowed. + @constant kBadReferenceErr -6740 An invalid or inappropriate reference was specified. + @constant kFlagErr -6741 An invalid, inappropriate, or unsupported flag was specified. + @constant kMalformedErr -6742 Something was not formed correctly. + @constant kSizeErr -6743 Size was too big, too small, or not appropriate. + @constant kNameErr -6744 Name was not correct, allowed, or appropriate. + @constant kNotReadyErr -6745 Device or service is not ready. + @constant kReadErr -6746 Could not read. + @constant kWriteErr -6747 Could not write. + @constant kMismatchErr -6748 Something does not match. + @constant kDateErr -6749 Date is invalid or out-of-range. + @constant kUnderrunErr -6750 Less data than expected. + @constant kOverrunErr -6751 More data than expected. + @constant kEndingErr -6752 Connection, session, or something is ending. + @constant kConnectionErr -6753 Connection failed or could not be established. + @constant kAuthenticationErr -6754 Authentication failed or is not supported. + @constant kOpenErr -6755 Could not open file, pipe, device, etc. + @constant kTypeErr -6756 Incorrect or incompatible type (e.g. file, data, etc.). + @constant kSkipErr -6757 Items should be or was skipped. + @constant kNoAckErr -6758 No acknowledge. + @constant kCollisionErr -6759 Collision occurred (e.g. two on bus at same time). + @constant kBackoffErr -6760 Backoff in progress and operation intentionally failed. + @constant kNoAddressAckErr -6761 No acknowledge of address. + @constant kBusyErr -6762 Cannot perform because something is busy. + @constant kNoSpaceErr -6763 Not enough space to perform operation. + */ + +#if ( TARGET_LANGUAGE_C_LIKE ) + #if ( !TARGET_OS_MAC && !TARGET_API_MAC_OSX_KERNEL ) +typedef int32_t OSStatus; + #endif #endif -#define kNoErr 0 -#define kInProgressErr 1 +#define kNoErr 0 +#define kInProgressErr 1 // Generic error codes are in the range -6700 to -6779. -#define kGenericErrorBase -6700 // Starting error code for all generic errors. - -#define kUnknownErr -6700 -#define kOptionErr -6701 -#define kSelectorErr -6702 -#define kExecutionStateErr -6703 -#define kPathErr -6704 -#define kParamErr -6705 -#define kParamCountErr -6706 -#define kCommandErr -6707 -#define kIDErr -6708 -#define kStateErr -6709 -#define kRangeErr -6710 -#define kRequestErr -6711 -#define kResponseErr -6712 -#define kChecksumErr -6713 -#define kNotHandledErr -6714 -#define kVersionErr -6715 -#define kSignatureErr -6716 -#define kFormatErr -6717 -#define kNotInitializedErr -6718 -#define kAlreadyInitializedErr -6719 -#define kNotInUseErr -6720 -#define kInUseErr -6721 -#define kTimeoutErr -6722 -#define kCanceledErr -6723 -#define kAlreadyCanceledErr -6724 -#define kCannotCancelErr -6725 -#define kDeletedErr -6726 -#define kNotFoundErr -6727 -#define kNoMemoryErr -6728 -#define kNoResourcesErr -6729 -#define kDuplicateErr -6730 -#define kImmutableErr -6731 -#define kUnsupportedDataErr -6732 -#define kIntegrityErr -6733 -#define kIncompatibleErr -6734 -#define kUnsupportedErr -6735 -#define kUnexpectedErr -6736 -#define kValueErr -6737 -#define kNotReadableErr -6738 -#define kNotWritableErr -6739 -#define kBadReferenceErr -6740 -#define kFlagErr -6741 -#define kMalformedErr -6742 -#define kSizeErr -6743 -#define kNameErr -6744 -#define kNotReadyErr -6745 -#define kReadErr -6746 -#define kWriteErr -6747 -#define kMismatchErr -6748 -#define kDateErr -6749 -#define kUnderrunErr -6750 -#define kOverrunErr -6751 -#define kEndingErr -6752 -#define kConnectionErr -6753 -#define kAuthenticationErr -6754 -#define kOpenErr -6755 -#define kTypeErr -6756 -#define kSkipErr -6757 -#define kNoAckErr -6758 -#define kCollisionErr -6759 -#define kBackoffErr -6760 -#define kNoAddressAckErr -6761 -#define kBusyErr -6762 -#define kNoSpaceErr -6763 +#define kGenericErrorBase -6700 // Starting error code for all generic errors. -#define kGenericErrorEnd -6779 // Last generic error code (inclusive) +#define kUnknownErr -6700 +#define kOptionErr -6701 +#define kSelectorErr -6702 +#define kExecutionStateErr -6703 +#define kPathErr -6704 +#define kParamErr -6705 +#define kParamCountErr -6706 +#define kCommandErr -6707 +#define kIDErr -6708 +#define kStateErr -6709 +#define kRangeErr -6710 +#define kRequestErr -6711 +#define kResponseErr -6712 +#define kChecksumErr -6713 +#define kNotHandledErr -6714 +#define kVersionErr -6715 +#define kSignatureErr -6716 +#define kFormatErr -6717 +#define kNotInitializedErr -6718 +#define kAlreadyInitializedErr -6719 +#define kNotInUseErr -6720 +#define kInUseErr -6721 +#define kTimeoutErr -6722 +#define kCanceledErr -6723 +#define kAlreadyCanceledErr -6724 +#define kCannotCancelErr -6725 +#define kDeletedErr -6726 +#define kNotFoundErr -6727 +#define kNoMemoryErr -6728 +#define kNoResourcesErr -6729 +#define kDuplicateErr -6730 +#define kImmutableErr -6731 +#define kUnsupportedDataErr -6732 +#define kIntegrityErr -6733 +#define kIncompatibleErr -6734 +#define kUnsupportedErr -6735 +#define kUnexpectedErr -6736 +#define kValueErr -6737 +#define kNotReadableErr -6738 +#define kNotWritableErr -6739 +#define kBadReferenceErr -6740 +#define kFlagErr -6741 +#define kMalformedErr -6742 +#define kSizeErr -6743 +#define kNameErr -6744 +#define kNotReadyErr -6745 +#define kReadErr -6746 +#define kWriteErr -6747 +#define kMismatchErr -6748 +#define kDateErr -6749 +#define kUnderrunErr -6750 +#define kOverrunErr -6751 +#define kEndingErr -6752 +#define kConnectionErr -6753 +#define kAuthenticationErr -6754 +#define kOpenErr -6755 +#define kTypeErr -6756 +#define kSkipErr -6757 +#define kNoAckErr -6758 +#define kCollisionErr -6759 +#define kBackoffErr -6760 +#define kNoAddressAckErr -6761 +#define kBusyErr -6762 +#define kNoSpaceErr -6763 + +#define kGenericErrorEnd -6779 // Last generic error code (inclusive) #if 0 #pragma mark == Mac Compatibility == @@ -1091,101 +1120,101 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @enum Duration - - @abstract Type used to specify a duration of time. - - @constant kDurationImmediate Indicates no delay/wait time. - @constant kDurationMicrosecond Microsecond units. - @constant kDurationMillisecond Millisecond units. - @constant kDurationSecond Second units. - @constant kDurationMinute Minute units. - @constant kDurationHour Hour units. - @constant kDurationDay Day units. - @constant kDurationForever Infinite period of time (no timeout). - @discussion - - Duration values are intended to be multiplied by the specific interval to achieve an actual duration. For example, - to wait for 5 seconds you would use "5 * kDurationSecond". -*/ + @abstract Type used to specify a duration of time. -#if( TARGET_LANGUAGE_C_LIKE ) - #if( !TARGET_OS_MAC ) - typedef int32_t Duration; - #endif + @constant kDurationImmediate Indicates no delay/wait time. + @constant kDurationMicrosecond Microsecond units. + @constant kDurationMillisecond Millisecond units. + @constant kDurationSecond Second units. + @constant kDurationMinute Minute units. + @constant kDurationHour Hour units. + @constant kDurationDay Day units. + @constant kDurationForever Infinite period of time (no timeout). + + @discussion + + Duration values are intended to be multiplied by the specific interval to achieve an actual duration. For example, + to wait for 5 seconds you would use "5 * kDurationSecond". + */ + +#if ( TARGET_LANGUAGE_C_LIKE ) + #if ( !TARGET_OS_MAC ) +typedef int32_t Duration; + #endif #endif -#define kDurationImmediate 0L -#define kDurationMicrosecond -1L -#define kDurationMillisecond 1L -#define kDurationSecond ( 1000L * kDurationMillisecond ) -#define kDurationMinute ( 60L * kDurationSecond ) -#define kDurationHour ( 60L * kDurationMinute ) -#define kDurationDay ( 24L * kDurationHour ) -#define kDurationForever 0x7FFFFFFFL +#define kDurationImmediate 0L +#define kDurationMicrosecond -1L +#define kDurationMillisecond 1L +#define kDurationSecond ( 1000L * kDurationMillisecond ) +#define kDurationMinute ( 60L * kDurationSecond ) +#define kDurationHour ( 60L * kDurationMinute ) +#define kDurationDay ( 24L * kDurationHour ) +#define kDurationForever 0x7FFFFFFFL // Seconds <-> Minutes <-> Hours <-> Days <-> Weeks <-> Months <-> Years conversions -#define kNanosecondsPerMicrosecond 1000 -#define kNanosecondsPerMillisecond 1000000 -#define kNanosecondsPerSecond 1000000000 -#define kMicrosecondsPerSecond 1000000 -#define kMicrosecondsPerMillisecond 1000 -#define kMillisecondsPerSecond 1000 -#define kSecondsPerMinute 60 -#define kSecondsPerHour ( 60 * 60 ) // 3600 -#define kSecondsPerDay ( 60 * 60 * 24 ) // 86400 -#define kSecondsPerWeek ( 60 * 60 * 24 * 7 ) // 604800 -#define kMinutesPerHour 60 -#define kMinutesPerDay ( 60 * 24 ) // 1440 -#define kHoursPerDay 24 -#define kDaysPerWeek 7 -#define kWeeksPerYear 52 -#define kMonthsPerYear 12 +#define kNanosecondsPerMicrosecond 1000 +#define kNanosecondsPerMillisecond 1000000 +#define kNanosecondsPerSecond 1000000000 +#define kMicrosecondsPerSecond 1000000 +#define kMicrosecondsPerMillisecond 1000 +#define kMillisecondsPerSecond 1000 +#define kSecondsPerMinute 60 +#define kSecondsPerHour ( 60 * 60 ) // 3600 +#define kSecondsPerDay ( 60 * 60 * 24 ) // 86400 +#define kSecondsPerWeek ( 60 * 60 * 24 * 7 ) // 604800 +#define kMinutesPerHour 60 +#define kMinutesPerDay ( 60 * 24 ) // 1440 +#define kHoursPerDay 24 +#define kDaysPerWeek 7 +#define kWeeksPerYear 52 +#define kMonthsPerYear 12 //--------------------------------------------------------------------------------------------------------------------------- /*! @defined VersionStages - @abstract NumVersion-style version stages. -*/ + @abstract NumVersion-style version stages. + */ -#define kVersionStageDevelopment 0x20 -#define kVersionStageAlpha 0x40 -#define kVersionStageBeta 0x60 -#define kVersionStageFinal 0x80 +#define kVersionStageDevelopment 0x20 +#define kVersionStageAlpha 0x40 +#define kVersionStageBeta 0x60 +#define kVersionStageFinal 0x80 //--------------------------------------------------------------------------------------------------------------------------- /*! @function NumVersionBuild - @abstract Builds a 32-bit Mac-style NumVersion value (e.g. NumVersionBuild( 1, 2, 3, kVersionStageBeta, 4 ) -> 1.2.3b4). -*/ + @abstract Builds a 32-bit Mac-style NumVersion value (e.g. NumVersionBuild( 1, 2, 3, kVersionStageBeta, 4 ) -> 1.2.3b4). + */ -#define NumVersionBuild( MAJOR, MINOR, BUGFIX, STAGE, REV ) \ - ( ( ( ( MAJOR ) & 0xFF ) << 24 ) | \ - ( ( ( MINOR ) & 0x0F ) << 20 ) | \ - ( ( ( BUGFIX ) & 0x0F ) << 16 ) | \ - ( ( ( STAGE ) & 0xFF ) << 8 ) | \ - ( ( ( REV ) & 0xFF ) ) ) +#define NumVersionBuild( MAJOR, MINOR, BUGFIX, STAGE, REV ) \ + ( ( ( ( MAJOR ) & 0xFF ) << 24 ) | \ + ( ( ( MINOR ) & 0x0F ) << 20 ) | \ + ( ( ( BUGFIX ) & 0x0F ) << 16 ) | \ + ( ( ( STAGE ) & 0xFF ) << 8 ) | \ + ( ( ( REV ) & 0xFF ) ) ) -#define NumVersionExtractMajor( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 24 ) & 0xFF ) ) -#define NumVersionExtractMinorAndBugFix( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 16 ) & 0xFF ) ) -#define NumVersionExtractMinor( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 20 ) & 0x0F ) ) -#define NumVersionExtractBugFix( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 16 ) & 0x0F ) ) -#define NumVersionExtractStage( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 8 ) & 0xFF ) ) -#define NumVersionExtractRevision( VERSION ) ( (uint8_t)( ( VERSION ) & 0xFF ) ) +#define NumVersionExtractMajor( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 24 ) & 0xFF ) ) +#define NumVersionExtractMinorAndBugFix( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 16 ) & 0xFF ) ) +#define NumVersionExtractMinor( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 20 ) & 0x0F ) ) +#define NumVersionExtractBugFix( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 16 ) & 0x0F ) ) +#define NumVersionExtractStage( VERSION ) ( (uint8_t)( ( ( VERSION ) >> 8 ) & 0xFF ) ) +#define NumVersionExtractRevision( VERSION ) ( (uint8_t)( ( VERSION ) & 0xFF ) ) //--------------------------------------------------------------------------------------------------------------------------- /*! @function NumVersionCompare - @abstract Compares two NumVersion values and returns the following values: - - left < right -> -1 - left > right -> 1 - left = right -> 0 -*/ + @abstract Compares two NumVersion values and returns the following values: -#if( TARGET_LANGUAGE_C_LIKE ) - int NumVersionCompare( uint32_t inLeft, uint32_t inRight ); + left < right -> -1 + left > right -> 1 + left = right -> 0 + */ + +#if ( TARGET_LANGUAGE_C_LIKE ) +int NumVersionCompare( uint32_t inLeft, uint32_t inRight ); #endif #if 0 @@ -1194,306 +1223,306 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @defined binary_4 - - @abstract Macro to generate an 4-bit constant using binary notation (e.g. binary_4( 1010 ) == 0xA). -*/ -#define binary_4( a ) binary_4_hex_wrap( hex_digit4( a ) ) -#define binary_4_hex_wrap( a ) binary_4_hex( a ) -#define binary_4_hex( a ) ( 0x ## a ) + @abstract Macro to generate an 4-bit constant using binary notation (e.g. binary_4( 1010 ) == 0xA). + */ + +#define binary_4( a ) binary_4_hex_wrap( hex_digit4( a ) ) +#define binary_4_hex_wrap( a ) binary_4_hex( a ) +#define binary_4_hex( a ) ( 0x ## a ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined binary_8 - - @abstract Macro to generate an 8-bit constant using binary notation (e.g. binary_8( 01111011 ) == 0x7B). -*/ -#define binary_8( a ) binary_8_hex_wrap( hex_digit8( a ) ) -#define binary_8_hex_wrap( a ) binary_8_hex( a ) -#define binary_8_hex( a ) ( 0x ## a ) + @abstract Macro to generate an 8-bit constant using binary notation (e.g. binary_8( 01111011 ) == 0x7B). + */ + +#define binary_8( a ) binary_8_hex_wrap( hex_digit8( a ) ) +#define binary_8_hex_wrap( a ) binary_8_hex( a ) +#define binary_8_hex( a ) ( 0x ## a ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined binary_16 - - @abstract Macro to generate an 16-bit constant using binary notation (e.g. binary_16( 01111011, 01111011 ) == 0x7B7B). -*/ -#define binary_16( a, b ) binary_16_hex_wrap( hex_digit8( a ), hex_digit8( b ) ) -#define binary_16_hex_wrap( a, b ) binary_16_hex( a, b ) -#define binary_16_hex( a, b ) ( 0x ## a ## b ) + @abstract Macro to generate an 16-bit constant using binary notation (e.g. binary_16( 01111011, 01111011 ) == 0x7B7B). + */ + +#define binary_16( a, b ) binary_16_hex_wrap( hex_digit8( a ), hex_digit8( b ) ) +#define binary_16_hex_wrap( a, b ) binary_16_hex( a, b ) +#define binary_16_hex( a, b ) ( 0x ## a ## b ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined binary_32 - - @abstract Macro to generate an 32-bit constant using binary notation - (e.g. binary_32( 01111011, 01111011, 01111011, 01111011 ) == 0x7B7B7B7B). -*/ -#define binary_32( a, b, c, d ) binary_32_hex_wrap( hex_digit8( a ), hex_digit8( b ), hex_digit8( c ), hex_digit8( d ) ) -#define binary_32_hex_wrap( a, b, c, d ) binary_32_hex( a, b, c, d ) -#define binary_32_hex( a, b, c, d ) ( 0x ## a ## b ## c ## d ) + @abstract Macro to generate an 32-bit constant using binary notation + (e.g. binary_32( 01111011, 01111011, 01111011, 01111011 ) == 0x7B7B7B7B). + */ + +#define binary_32( a, b, c, d ) binary_32_hex_wrap( hex_digit8( a ), hex_digit8( b ), hex_digit8( c ), hex_digit8( d ) ) +#define binary_32_hex_wrap( a, b, c, d ) binary_32_hex( a, b, c, d ) +#define binary_32_hex( a, b, c, d ) ( 0x ## a ## b ## c ## d ) // Binary Constant Helpers -#define hex_digit8( a ) HEX_DIGIT_ ## a -#define hex_digit4( a ) HEX_DIGIT_ ## 0000 ## a +#define hex_digit8( a ) HEX_DIGIT_ ## a +#define hex_digit4( a ) HEX_DIGIT_ ## 0000 ## a -#define HEX_DIGIT_00000000 00 -#define HEX_DIGIT_00000001 01 -#define HEX_DIGIT_00000010 02 -#define HEX_DIGIT_00000011 03 -#define HEX_DIGIT_00000100 04 -#define HEX_DIGIT_00000101 05 -#define HEX_DIGIT_00000110 06 -#define HEX_DIGIT_00000111 07 -#define HEX_DIGIT_00001000 08 -#define HEX_DIGIT_00001001 09 -#define HEX_DIGIT_00001010 0A -#define HEX_DIGIT_00001011 0B -#define HEX_DIGIT_00001100 0C -#define HEX_DIGIT_00001101 0D -#define HEX_DIGIT_00001110 0E -#define HEX_DIGIT_00001111 0F -#define HEX_DIGIT_00010000 10 -#define HEX_DIGIT_00010001 11 -#define HEX_DIGIT_00010010 12 -#define HEX_DIGIT_00010011 13 -#define HEX_DIGIT_00010100 14 -#define HEX_DIGIT_00010101 15 -#define HEX_DIGIT_00010110 16 -#define HEX_DIGIT_00010111 17 -#define HEX_DIGIT_00011000 18 -#define HEX_DIGIT_00011001 19 -#define HEX_DIGIT_00011010 1A -#define HEX_DIGIT_00011011 1B -#define HEX_DIGIT_00011100 1C -#define HEX_DIGIT_00011101 1D -#define HEX_DIGIT_00011110 1E -#define HEX_DIGIT_00011111 1F -#define HEX_DIGIT_00100000 20 -#define HEX_DIGIT_00100001 21 -#define HEX_DIGIT_00100010 22 -#define HEX_DIGIT_00100011 23 -#define HEX_DIGIT_00100100 24 -#define HEX_DIGIT_00100101 25 -#define HEX_DIGIT_00100110 26 -#define HEX_DIGIT_00100111 27 -#define HEX_DIGIT_00101000 28 -#define HEX_DIGIT_00101001 29 -#define HEX_DIGIT_00101010 2A -#define HEX_DIGIT_00101011 2B -#define HEX_DIGIT_00101100 2C -#define HEX_DIGIT_00101101 2D -#define HEX_DIGIT_00101110 2E -#define HEX_DIGIT_00101111 2F -#define HEX_DIGIT_00110000 30 -#define HEX_DIGIT_00110001 31 -#define HEX_DIGIT_00110010 32 -#define HEX_DIGIT_00110011 33 -#define HEX_DIGIT_00110100 34 -#define HEX_DIGIT_00110101 35 -#define HEX_DIGIT_00110110 36 -#define HEX_DIGIT_00110111 37 -#define HEX_DIGIT_00111000 38 -#define HEX_DIGIT_00111001 39 -#define HEX_DIGIT_00111010 3A -#define HEX_DIGIT_00111011 3B -#define HEX_DIGIT_00111100 3C -#define HEX_DIGIT_00111101 3D -#define HEX_DIGIT_00111110 3E -#define HEX_DIGIT_00111111 3F -#define HEX_DIGIT_01000000 40 -#define HEX_DIGIT_01000001 41 -#define HEX_DIGIT_01000010 42 -#define HEX_DIGIT_01000011 43 -#define HEX_DIGIT_01000100 44 -#define HEX_DIGIT_01000101 45 -#define HEX_DIGIT_01000110 46 -#define HEX_DIGIT_01000111 47 -#define HEX_DIGIT_01001000 48 -#define HEX_DIGIT_01001001 49 -#define HEX_DIGIT_01001010 4A -#define HEX_DIGIT_01001011 4B -#define HEX_DIGIT_01001100 4C -#define HEX_DIGIT_01001101 4D -#define HEX_DIGIT_01001110 4E -#define HEX_DIGIT_01001111 4F -#define HEX_DIGIT_01010000 50 -#define HEX_DIGIT_01010001 51 -#define HEX_DIGIT_01010010 52 -#define HEX_DIGIT_01010011 53 -#define HEX_DIGIT_01010100 54 -#define HEX_DIGIT_01010101 55 -#define HEX_DIGIT_01010110 56 -#define HEX_DIGIT_01010111 57 -#define HEX_DIGIT_01011000 58 -#define HEX_DIGIT_01011001 59 -#define HEX_DIGIT_01011010 5A -#define HEX_DIGIT_01011011 5B -#define HEX_DIGIT_01011100 5C -#define HEX_DIGIT_01011101 5D -#define HEX_DIGIT_01011110 5E -#define HEX_DIGIT_01011111 5F -#define HEX_DIGIT_01100000 60 -#define HEX_DIGIT_01100001 61 -#define HEX_DIGIT_01100010 62 -#define HEX_DIGIT_01100011 63 -#define HEX_DIGIT_01100100 64 -#define HEX_DIGIT_01100101 65 -#define HEX_DIGIT_01100110 66 -#define HEX_DIGIT_01100111 67 -#define HEX_DIGIT_01101000 68 -#define HEX_DIGIT_01101001 69 -#define HEX_DIGIT_01101010 6A -#define HEX_DIGIT_01101011 6B -#define HEX_DIGIT_01101100 6C -#define HEX_DIGIT_01101101 6D -#define HEX_DIGIT_01101110 6E -#define HEX_DIGIT_01101111 6F -#define HEX_DIGIT_01110000 70 -#define HEX_DIGIT_01110001 71 -#define HEX_DIGIT_01110010 72 -#define HEX_DIGIT_01110011 73 -#define HEX_DIGIT_01110100 74 -#define HEX_DIGIT_01110101 75 -#define HEX_DIGIT_01110110 76 -#define HEX_DIGIT_01110111 77 -#define HEX_DIGIT_01111000 78 -#define HEX_DIGIT_01111001 79 -#define HEX_DIGIT_01111010 7A -#define HEX_DIGIT_01111011 7B -#define HEX_DIGIT_01111100 7C -#define HEX_DIGIT_01111101 7D -#define HEX_DIGIT_01111110 7E -#define HEX_DIGIT_01111111 7F -#define HEX_DIGIT_10000000 80 -#define HEX_DIGIT_10000001 81 -#define HEX_DIGIT_10000010 82 -#define HEX_DIGIT_10000011 83 -#define HEX_DIGIT_10000100 84 -#define HEX_DIGIT_10000101 85 -#define HEX_DIGIT_10000110 86 -#define HEX_DIGIT_10000111 87 -#define HEX_DIGIT_10001000 88 -#define HEX_DIGIT_10001001 89 -#define HEX_DIGIT_10001010 8A -#define HEX_DIGIT_10001011 8B -#define HEX_DIGIT_10001100 8C -#define HEX_DIGIT_10001101 8D -#define HEX_DIGIT_10001110 8E -#define HEX_DIGIT_10001111 8F -#define HEX_DIGIT_10010000 90 -#define HEX_DIGIT_10010001 91 -#define HEX_DIGIT_10010010 92 -#define HEX_DIGIT_10010011 93 -#define HEX_DIGIT_10010100 94 -#define HEX_DIGIT_10010101 95 -#define HEX_DIGIT_10010110 96 -#define HEX_DIGIT_10010111 97 -#define HEX_DIGIT_10011000 98 -#define HEX_DIGIT_10011001 99 -#define HEX_DIGIT_10011010 9A -#define HEX_DIGIT_10011011 9B -#define HEX_DIGIT_10011100 9C -#define HEX_DIGIT_10011101 9D -#define HEX_DIGIT_10011110 9E -#define HEX_DIGIT_10011111 9F -#define HEX_DIGIT_10100000 A0 -#define HEX_DIGIT_10100001 A1 -#define HEX_DIGIT_10100010 A2 -#define HEX_DIGIT_10100011 A3 -#define HEX_DIGIT_10100100 A4 -#define HEX_DIGIT_10100101 A5 -#define HEX_DIGIT_10100110 A6 -#define HEX_DIGIT_10100111 A7 -#define HEX_DIGIT_10101000 A8 -#define HEX_DIGIT_10101001 A9 -#define HEX_DIGIT_10101010 AA -#define HEX_DIGIT_10101011 AB -#define HEX_DIGIT_10101100 AC -#define HEX_DIGIT_10101101 AD -#define HEX_DIGIT_10101110 AE -#define HEX_DIGIT_10101111 AF -#define HEX_DIGIT_10110000 B0 -#define HEX_DIGIT_10110001 B1 -#define HEX_DIGIT_10110010 B2 -#define HEX_DIGIT_10110011 B3 -#define HEX_DIGIT_10110100 B4 -#define HEX_DIGIT_10110101 B5 -#define HEX_DIGIT_10110110 B6 -#define HEX_DIGIT_10110111 B7 -#define HEX_DIGIT_10111000 B8 -#define HEX_DIGIT_10111001 B9 -#define HEX_DIGIT_10111010 BA -#define HEX_DIGIT_10111011 BB -#define HEX_DIGIT_10111100 BC -#define HEX_DIGIT_10111101 BD -#define HEX_DIGIT_10111110 BE -#define HEX_DIGIT_10111111 BF -#define HEX_DIGIT_11000000 C0 -#define HEX_DIGIT_11000001 C1 -#define HEX_DIGIT_11000010 C2 -#define HEX_DIGIT_11000011 C3 -#define HEX_DIGIT_11000100 C4 -#define HEX_DIGIT_11000101 C5 -#define HEX_DIGIT_11000110 C6 -#define HEX_DIGIT_11000111 C7 -#define HEX_DIGIT_11001000 C8 -#define HEX_DIGIT_11001001 C9 -#define HEX_DIGIT_11001010 CA -#define HEX_DIGIT_11001011 CB -#define HEX_DIGIT_11001100 CC -#define HEX_DIGIT_11001101 CD -#define HEX_DIGIT_11001110 CE -#define HEX_DIGIT_11001111 CF -#define HEX_DIGIT_11010000 D0 -#define HEX_DIGIT_11010001 D1 -#define HEX_DIGIT_11010010 D2 -#define HEX_DIGIT_11010011 D3 -#define HEX_DIGIT_11010100 D4 -#define HEX_DIGIT_11010101 D5 -#define HEX_DIGIT_11010110 D6 -#define HEX_DIGIT_11010111 D7 -#define HEX_DIGIT_11011000 D8 -#define HEX_DIGIT_11011001 D9 -#define HEX_DIGIT_11011010 DA -#define HEX_DIGIT_11011011 DB -#define HEX_DIGIT_11011100 DC -#define HEX_DIGIT_11011101 DD -#define HEX_DIGIT_11011110 DE -#define HEX_DIGIT_11011111 DF -#define HEX_DIGIT_11100000 E0 -#define HEX_DIGIT_11100001 E1 -#define HEX_DIGIT_11100010 E2 -#define HEX_DIGIT_11100011 E3 -#define HEX_DIGIT_11100100 E4 -#define HEX_DIGIT_11100101 E5 -#define HEX_DIGIT_11100110 E6 -#define HEX_DIGIT_11100111 E7 -#define HEX_DIGIT_11101000 E8 -#define HEX_DIGIT_11101001 E9 -#define HEX_DIGIT_11101010 EA -#define HEX_DIGIT_11101011 EB -#define HEX_DIGIT_11101100 EC -#define HEX_DIGIT_11101101 ED -#define HEX_DIGIT_11101110 EE -#define HEX_DIGIT_11101111 EF -#define HEX_DIGIT_11110000 F0 -#define HEX_DIGIT_11110001 F1 -#define HEX_DIGIT_11110010 F2 -#define HEX_DIGIT_11110011 F3 -#define HEX_DIGIT_11110100 F4 -#define HEX_DIGIT_11110101 F5 -#define HEX_DIGIT_11110110 F6 -#define HEX_DIGIT_11110111 F7 -#define HEX_DIGIT_11111000 F8 -#define HEX_DIGIT_11111001 F9 -#define HEX_DIGIT_11111010 FA -#define HEX_DIGIT_11111011 FB -#define HEX_DIGIT_11111100 FC -#define HEX_DIGIT_11111101 FD -#define HEX_DIGIT_11111110 FE -#define HEX_DIGIT_11111111 FF +#define HEX_DIGIT_00000000 00 +#define HEX_DIGIT_00000001 01 +#define HEX_DIGIT_00000010 02 +#define HEX_DIGIT_00000011 03 +#define HEX_DIGIT_00000100 04 +#define HEX_DIGIT_00000101 05 +#define HEX_DIGIT_00000110 06 +#define HEX_DIGIT_00000111 07 +#define HEX_DIGIT_00001000 08 +#define HEX_DIGIT_00001001 09 +#define HEX_DIGIT_00001010 0A +#define HEX_DIGIT_00001011 0B +#define HEX_DIGIT_00001100 0C +#define HEX_DIGIT_00001101 0D +#define HEX_DIGIT_00001110 0E +#define HEX_DIGIT_00001111 0F +#define HEX_DIGIT_00010000 10 +#define HEX_DIGIT_00010001 11 +#define HEX_DIGIT_00010010 12 +#define HEX_DIGIT_00010011 13 +#define HEX_DIGIT_00010100 14 +#define HEX_DIGIT_00010101 15 +#define HEX_DIGIT_00010110 16 +#define HEX_DIGIT_00010111 17 +#define HEX_DIGIT_00011000 18 +#define HEX_DIGIT_00011001 19 +#define HEX_DIGIT_00011010 1A +#define HEX_DIGIT_00011011 1B +#define HEX_DIGIT_00011100 1C +#define HEX_DIGIT_00011101 1D +#define HEX_DIGIT_00011110 1E +#define HEX_DIGIT_00011111 1F +#define HEX_DIGIT_00100000 20 +#define HEX_DIGIT_00100001 21 +#define HEX_DIGIT_00100010 22 +#define HEX_DIGIT_00100011 23 +#define HEX_DIGIT_00100100 24 +#define HEX_DIGIT_00100101 25 +#define HEX_DIGIT_00100110 26 +#define HEX_DIGIT_00100111 27 +#define HEX_DIGIT_00101000 28 +#define HEX_DIGIT_00101001 29 +#define HEX_DIGIT_00101010 2A +#define HEX_DIGIT_00101011 2B +#define HEX_DIGIT_00101100 2C +#define HEX_DIGIT_00101101 2D +#define HEX_DIGIT_00101110 2E +#define HEX_DIGIT_00101111 2F +#define HEX_DIGIT_00110000 30 +#define HEX_DIGIT_00110001 31 +#define HEX_DIGIT_00110010 32 +#define HEX_DIGIT_00110011 33 +#define HEX_DIGIT_00110100 34 +#define HEX_DIGIT_00110101 35 +#define HEX_DIGIT_00110110 36 +#define HEX_DIGIT_00110111 37 +#define HEX_DIGIT_00111000 38 +#define HEX_DIGIT_00111001 39 +#define HEX_DIGIT_00111010 3A +#define HEX_DIGIT_00111011 3B +#define HEX_DIGIT_00111100 3C +#define HEX_DIGIT_00111101 3D +#define HEX_DIGIT_00111110 3E +#define HEX_DIGIT_00111111 3F +#define HEX_DIGIT_01000000 40 +#define HEX_DIGIT_01000001 41 +#define HEX_DIGIT_01000010 42 +#define HEX_DIGIT_01000011 43 +#define HEX_DIGIT_01000100 44 +#define HEX_DIGIT_01000101 45 +#define HEX_DIGIT_01000110 46 +#define HEX_DIGIT_01000111 47 +#define HEX_DIGIT_01001000 48 +#define HEX_DIGIT_01001001 49 +#define HEX_DIGIT_01001010 4A +#define HEX_DIGIT_01001011 4B +#define HEX_DIGIT_01001100 4C +#define HEX_DIGIT_01001101 4D +#define HEX_DIGIT_01001110 4E +#define HEX_DIGIT_01001111 4F +#define HEX_DIGIT_01010000 50 +#define HEX_DIGIT_01010001 51 +#define HEX_DIGIT_01010010 52 +#define HEX_DIGIT_01010011 53 +#define HEX_DIGIT_01010100 54 +#define HEX_DIGIT_01010101 55 +#define HEX_DIGIT_01010110 56 +#define HEX_DIGIT_01010111 57 +#define HEX_DIGIT_01011000 58 +#define HEX_DIGIT_01011001 59 +#define HEX_DIGIT_01011010 5A +#define HEX_DIGIT_01011011 5B +#define HEX_DIGIT_01011100 5C +#define HEX_DIGIT_01011101 5D +#define HEX_DIGIT_01011110 5E +#define HEX_DIGIT_01011111 5F +#define HEX_DIGIT_01100000 60 +#define HEX_DIGIT_01100001 61 +#define HEX_DIGIT_01100010 62 +#define HEX_DIGIT_01100011 63 +#define HEX_DIGIT_01100100 64 +#define HEX_DIGIT_01100101 65 +#define HEX_DIGIT_01100110 66 +#define HEX_DIGIT_01100111 67 +#define HEX_DIGIT_01101000 68 +#define HEX_DIGIT_01101001 69 +#define HEX_DIGIT_01101010 6A +#define HEX_DIGIT_01101011 6B +#define HEX_DIGIT_01101100 6C +#define HEX_DIGIT_01101101 6D +#define HEX_DIGIT_01101110 6E +#define HEX_DIGIT_01101111 6F +#define HEX_DIGIT_01110000 70 +#define HEX_DIGIT_01110001 71 +#define HEX_DIGIT_01110010 72 +#define HEX_DIGIT_01110011 73 +#define HEX_DIGIT_01110100 74 +#define HEX_DIGIT_01110101 75 +#define HEX_DIGIT_01110110 76 +#define HEX_DIGIT_01110111 77 +#define HEX_DIGIT_01111000 78 +#define HEX_DIGIT_01111001 79 +#define HEX_DIGIT_01111010 7A +#define HEX_DIGIT_01111011 7B +#define HEX_DIGIT_01111100 7C +#define HEX_DIGIT_01111101 7D +#define HEX_DIGIT_01111110 7E +#define HEX_DIGIT_01111111 7F +#define HEX_DIGIT_10000000 80 +#define HEX_DIGIT_10000001 81 +#define HEX_DIGIT_10000010 82 +#define HEX_DIGIT_10000011 83 +#define HEX_DIGIT_10000100 84 +#define HEX_DIGIT_10000101 85 +#define HEX_DIGIT_10000110 86 +#define HEX_DIGIT_10000111 87 +#define HEX_DIGIT_10001000 88 +#define HEX_DIGIT_10001001 89 +#define HEX_DIGIT_10001010 8A +#define HEX_DIGIT_10001011 8B +#define HEX_DIGIT_10001100 8C +#define HEX_DIGIT_10001101 8D +#define HEX_DIGIT_10001110 8E +#define HEX_DIGIT_10001111 8F +#define HEX_DIGIT_10010000 90 +#define HEX_DIGIT_10010001 91 +#define HEX_DIGIT_10010010 92 +#define HEX_DIGIT_10010011 93 +#define HEX_DIGIT_10010100 94 +#define HEX_DIGIT_10010101 95 +#define HEX_DIGIT_10010110 96 +#define HEX_DIGIT_10010111 97 +#define HEX_DIGIT_10011000 98 +#define HEX_DIGIT_10011001 99 +#define HEX_DIGIT_10011010 9A +#define HEX_DIGIT_10011011 9B +#define HEX_DIGIT_10011100 9C +#define HEX_DIGIT_10011101 9D +#define HEX_DIGIT_10011110 9E +#define HEX_DIGIT_10011111 9F +#define HEX_DIGIT_10100000 A0 +#define HEX_DIGIT_10100001 A1 +#define HEX_DIGIT_10100010 A2 +#define HEX_DIGIT_10100011 A3 +#define HEX_DIGIT_10100100 A4 +#define HEX_DIGIT_10100101 A5 +#define HEX_DIGIT_10100110 A6 +#define HEX_DIGIT_10100111 A7 +#define HEX_DIGIT_10101000 A8 +#define HEX_DIGIT_10101001 A9 +#define HEX_DIGIT_10101010 AA +#define HEX_DIGIT_10101011 AB +#define HEX_DIGIT_10101100 AC +#define HEX_DIGIT_10101101 AD +#define HEX_DIGIT_10101110 AE +#define HEX_DIGIT_10101111 AF +#define HEX_DIGIT_10110000 B0 +#define HEX_DIGIT_10110001 B1 +#define HEX_DIGIT_10110010 B2 +#define HEX_DIGIT_10110011 B3 +#define HEX_DIGIT_10110100 B4 +#define HEX_DIGIT_10110101 B5 +#define HEX_DIGIT_10110110 B6 +#define HEX_DIGIT_10110111 B7 +#define HEX_DIGIT_10111000 B8 +#define HEX_DIGIT_10111001 B9 +#define HEX_DIGIT_10111010 BA +#define HEX_DIGIT_10111011 BB +#define HEX_DIGIT_10111100 BC +#define HEX_DIGIT_10111101 BD +#define HEX_DIGIT_10111110 BE +#define HEX_DIGIT_10111111 BF +#define HEX_DIGIT_11000000 C0 +#define HEX_DIGIT_11000001 C1 +#define HEX_DIGIT_11000010 C2 +#define HEX_DIGIT_11000011 C3 +#define HEX_DIGIT_11000100 C4 +#define HEX_DIGIT_11000101 C5 +#define HEX_DIGIT_11000110 C6 +#define HEX_DIGIT_11000111 C7 +#define HEX_DIGIT_11001000 C8 +#define HEX_DIGIT_11001001 C9 +#define HEX_DIGIT_11001010 CA +#define HEX_DIGIT_11001011 CB +#define HEX_DIGIT_11001100 CC +#define HEX_DIGIT_11001101 CD +#define HEX_DIGIT_11001110 CE +#define HEX_DIGIT_11001111 CF +#define HEX_DIGIT_11010000 D0 +#define HEX_DIGIT_11010001 D1 +#define HEX_DIGIT_11010010 D2 +#define HEX_DIGIT_11010011 D3 +#define HEX_DIGIT_11010100 D4 +#define HEX_DIGIT_11010101 D5 +#define HEX_DIGIT_11010110 D6 +#define HEX_DIGIT_11010111 D7 +#define HEX_DIGIT_11011000 D8 +#define HEX_DIGIT_11011001 D9 +#define HEX_DIGIT_11011010 DA +#define HEX_DIGIT_11011011 DB +#define HEX_DIGIT_11011100 DC +#define HEX_DIGIT_11011101 DD +#define HEX_DIGIT_11011110 DE +#define HEX_DIGIT_11011111 DF +#define HEX_DIGIT_11100000 E0 +#define HEX_DIGIT_11100001 E1 +#define HEX_DIGIT_11100010 E2 +#define HEX_DIGIT_11100011 E3 +#define HEX_DIGIT_11100100 E4 +#define HEX_DIGIT_11100101 E5 +#define HEX_DIGIT_11100110 E6 +#define HEX_DIGIT_11100111 E7 +#define HEX_DIGIT_11101000 E8 +#define HEX_DIGIT_11101001 E9 +#define HEX_DIGIT_11101010 EA +#define HEX_DIGIT_11101011 EB +#define HEX_DIGIT_11101100 EC +#define HEX_DIGIT_11101101 ED +#define HEX_DIGIT_11101110 EE +#define HEX_DIGIT_11101111 EF +#define HEX_DIGIT_11110000 F0 +#define HEX_DIGIT_11110001 F1 +#define HEX_DIGIT_11110010 F2 +#define HEX_DIGIT_11110011 F3 +#define HEX_DIGIT_11110100 F4 +#define HEX_DIGIT_11110101 F5 +#define HEX_DIGIT_11110110 F6 +#define HEX_DIGIT_11110111 F7 +#define HEX_DIGIT_11111000 F8 +#define HEX_DIGIT_11111001 F9 +#define HEX_DIGIT_11111010 FA +#define HEX_DIGIT_11111011 FB +#define HEX_DIGIT_11111100 FC +#define HEX_DIGIT_11111101 FD +#define HEX_DIGIT_11111110 FE +#define HEX_DIGIT_11111111 FF #if 0 #pragma mark == Debugging == @@ -1502,17 +1531,17 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @function CommonServicesTest - @abstract Unit test. -*/ + @abstract Unit test. + */ -#if( DEBUG ) - #if( TARGET_LANGUAGE_C_LIKE ) - OSStatus CommonServicesTest( void ); - #endif +#if ( DEBUG ) + #if ( TARGET_LANGUAGE_C_LIKE ) +OSStatus CommonServicesTest( void ); + #endif #endif -#ifdef __cplusplus - } +#ifdef __cplusplus +} #endif -#endif // __COMMON_SERVICES__ +#endif // __COMMON_SERVICES__ diff --git a/bonjour-sdk/DebugServices.h b/bonjour-sdk/DebugServices.h index d4e5c72..108f7f5 100644 --- a/bonjour-sdk/DebugServices.h +++ b/bonjour-sdk/DebugServices.h @@ -5,9 +5,9 @@ * 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. @@ -18,18 +18,18 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @header DebugServices - Debugging Library -*/ + Debugging Library + */ -#ifndef __DEBUG_SERVICES__ -#define __DEBUG_SERVICES__ +#ifndef __DEBUG_SERVICES__ +#define __DEBUG_SERVICES__ -#include +#include -#include "CommonServices.h" +#include "CommonServices.h" -#if( TARGET_OS_VXWORKS ) - #include "logLib.h" +#if ( TARGET_OS_VXWORKS ) + #include "logLib.h" #endif #if 0 @@ -42,48 +42,48 @@ // General -#if( !defined( DEBUG ) ) - #define DEBUG 0 +#if ( !defined( DEBUG ) ) + #define DEBUG 0 #endif -#if( defined( NDEBUG ) && DEBUG ) - #error NDEBUG defined and DEBUG is also enabled...they need to be in-sync +#if ( defined( NDEBUG ) && DEBUG ) + #error NDEBUG defined and DEBUG is also enabled...they need to be in-sync #endif - + // AssertMacros.h/Debugging.h overrides. -#if( !defined( DEBUG_OVERRIDE_APPLE_MACROS ) ) - #define DEBUG_OVERRIDE_APPLE_MACROS 1 +#if ( !defined( DEBUG_OVERRIDE_APPLE_MACROS ) ) + #define DEBUG_OVERRIDE_APPLE_MACROS 1 #endif // Routine name. Uses ISO __func__ where possible. Otherwise, uses the best thing that is available (if anything). -#if( defined( __MWERKS__ ) || ( __GNUC__ > 2 ) || ( ( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 9 ) ) ) - #define __ROUTINE__ __func__ -#elif( defined( __GNUC__ ) ) - #define __ROUTINE__ __PRETTY_FUNCTION__ -#elif( defined( _MSC_VER ) && !defined( _WIN32_WCE ) ) - #define __ROUTINE__ __FUNCTION__ +#if ( defined( __MWERKS__ ) || ( __GNUC__ > 2 ) || ( ( __GNUC__ == 2 ) && ( __GNUC_MINOR__ >= 9 ) ) ) + #define __ROUTINE__ __func__ +#elif ( defined( __GNUC__ ) ) + #define __ROUTINE__ __PRETTY_FUNCTION__ +#elif ( defined( _MSC_VER ) && !defined( _WIN32_WCE ) ) + #define __ROUTINE__ __FUNCTION__ #else - #define __ROUTINE__ "" + #define __ROUTINE__ "" #endif // Variable argument macro support. Use ANSI C99 __VA_ARGS__ where possible. Otherwise, use the next best thing. -#if( defined( __GNUC__ ) ) - #if( ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 3) ) ) - #define DEBUG_C99_VA_ARGS 1 - #define DEBUG_GNU_VA_ARGS 0 - #else - #define DEBUG_C99_VA_ARGS 0 - #define DEBUG_GNU_VA_ARGS 1 - #endif -#elif( defined( __MWERKS__ ) ) - #define DEBUG_C99_VA_ARGS 1 - #define DEBUG_GNU_VA_ARGS 0 +#if ( defined( __GNUC__ ) ) + #if ( ( __GNUC__ > 3 ) || ( ( __GNUC__ == 3 ) && ( __GNUC_MINOR__ >= 3) ) ) + #define DEBUG_C99_VA_ARGS 1 + #define DEBUG_GNU_VA_ARGS 0 + #else + #define DEBUG_C99_VA_ARGS 0 + #define DEBUG_GNU_VA_ARGS 1 + #endif +#elif ( defined( __MWERKS__ ) ) + #define DEBUG_C99_VA_ARGS 1 + #define DEBUG_GNU_VA_ARGS 0 #else - #define DEBUG_C99_VA_ARGS 0 - #define DEBUG_GNU_VA_ARGS 0 + #define DEBUG_C99_VA_ARGS 0 + #define DEBUG_GNU_VA_ARGS 0 #endif #if 0 @@ -92,122 +92,122 @@ //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_FPRINTF_ENABLED - - @abstract Enables ANSI C fprintf output. -*/ -#if( !defined( DEBUG_FPRINTF_ENABLED ) ) - #if( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) - #define DEBUG_FPRINTF_ENABLED 1 - #else - #define DEBUG_FPRINTF_ENABLED 0 - #endif + @abstract Enables ANSI C fprintf output. + */ + +#if ( !defined( DEBUG_FPRINTF_ENABLED ) ) + #if ( !TARGET_API_MAC_OSX_KERNEL && !TARGET_OS_WINDOWS_CE ) + #define DEBUG_FPRINTF_ENABLED 1 + #else + #define DEBUG_FPRINTF_ENABLED 0 + #endif #else - #if( TARGET_API_MAC_OSX_KERNEL || TARGET_OS_WINDOWS_CE ) - #error fprintf enabled, but not supported on Mac OS X kernel or Windows CE - #endif + #if ( TARGET_API_MAC_OSX_KERNEL || TARGET_OS_WINDOWS_CE ) + #error fprintf enabled, but not supported on Mac OS X kernel or Windows CE + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_MAC_OS_X_IOLOG_ENABLED - - @abstract Enables IOLog (Mac OS X Kernel) output. -*/ -#if( !defined( DEBUG_MAC_OS_X_IOLOG_ENABLED ) ) - #define DEBUG_MAC_OS_X_IOLOG_ENABLED TARGET_API_MAC_OSX_KERNEL + @abstract Enables IOLog (Mac OS X Kernel) output. + */ + +#if ( !defined( DEBUG_MAC_OS_X_IOLOG_ENABLED ) ) + #define DEBUG_MAC_OS_X_IOLOG_ENABLED TARGET_API_MAC_OSX_KERNEL #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_KPRINTF_ENABLED - - @abstract Enables kprintf (Mac OS X Kernel) output. -*/ -#if( !defined( DEBUG_KPRINTF_ENABLED ) ) - #define DEBUG_KPRINTF_ENABLED TARGET_API_MAC_OSX_KERNEL + @abstract Enables kprintf (Mac OS X Kernel) output. + */ + +#if ( !defined( DEBUG_KPRINTF_ENABLED ) ) + #define DEBUG_KPRINTF_ENABLED TARGET_API_MAC_OSX_KERNEL #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_IDEBUG_ENABLED - - @abstract Enables iDebug (Mac OS X user and Kernel) output. - - @discussion - - For Mac OS X kernel development, iDebug is enabled by default because we can dynamically check for the presence - of iDebug via some exported IOKit symbols. Mac OS X app usage doesn't allow dynamic detection because it relies - on statically linking to the iDebugServices.cp file so for Mac OS X app usage, you have to manually enable iDebug. -*/ -#if( !defined( DEBUG_IDEBUG_ENABLED ) ) - #define DEBUG_IDEBUG_ENABLED TARGET_API_MAC_OSX_KERNEL + @abstract Enables iDebug (Mac OS X user and Kernel) output. + + @discussion + + For Mac OS X kernel development, iDebug is enabled by default because we can dynamically check for the presence + of iDebug via some exported IOKit symbols. Mac OS X app usage doesn't allow dynamic detection because it relies + on statically linking to the iDebugServices.cp file so for Mac OS X app usage, you have to manually enable iDebug. + */ + +#if ( !defined( DEBUG_IDEBUG_ENABLED ) ) + #define DEBUG_IDEBUG_ENABLED TARGET_API_MAC_OSX_KERNEL #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_CORE_SERVICE_ASSERTS_ENABLED - - @abstract Controls whether Core Services assert handling is enabled. Enabling requires CoreServices framework. -*/ -#if( !defined( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) ) - #if( defined( __DEBUGGING__ ) ) - #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 1 - #else - #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 0 - #endif + @abstract Controls whether Core Services assert handling is enabled. Enabling requires CoreServices framework. + */ + +#if ( !defined( DEBUG_CORE_SERVICE_ASSERTS_ENABLED ) ) + #if ( defined( __DEBUGGING__ ) ) + #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 1 + #else + #define DEBUG_CORE_SERVICE_ASSERTS_ENABLED 0 + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef DebugOutputType - - @abstract Type of debug output (i.e. where the output goes). -*/ -typedef uint32_t DebugOutputType; + @abstract Type of debug output (i.e. where the output goes). + */ -#define kDebugOutputTypeNone 0x6E6F6E65U // 'none' - no params -#define kDebugOutputTypeCustom 0x63757374U // 'cust' - 1st param = function ptr, 2nd param = context -#define kDebugOutputTypeFPrintF 0x66707269U // 'fpri' - 1st param = DebugOutputTypeFlags [, 2nd param = filename] -#define kDebugOutputTypeiDebug 0x69646267U // 'idbg' - no params -#define kDebugOutputTypeKPrintF 0x6B707266U // 'kprf' - no params -#define kDebugOutputTypeMacOSXIOLog 0x696C6F67U // 'ilog' - no params -#define kDebugOutputTypeMacOSXLog 0x786C6F67U // 'xlog' - no params -#define kDebugOutputTypeWindowsDebugger 0x77696E64U // 'wind' - no params -#define kDebugOutputTypeWindowsEventLog 0x7765766CU // 'wevl' - 1st param = C-string name, 2nd param = HMODULE or NULL. +typedef uint32_t DebugOutputType; + +#define kDebugOutputTypeNone 0x6E6F6E65U // 'none' - no params +#define kDebugOutputTypeCustom 0x63757374U // 'cust' - 1st param = function ptr, 2nd param = context +#define kDebugOutputTypeFPrintF 0x66707269U // 'fpri' - 1st param = DebugOutputTypeFlags [, 2nd param = filename] +#define kDebugOutputTypeiDebug 0x69646267U // 'idbg' - no params +#define kDebugOutputTypeKPrintF 0x6B707266U // 'kprf' - no params +#define kDebugOutputTypeMacOSXIOLog 0x696C6F67U // 'ilog' - no params +#define kDebugOutputTypeMacOSXLog 0x786C6F67U // 'xlog' - no params +#define kDebugOutputTypeWindowsDebugger 0x77696E64U // 'wind' - no params +#define kDebugOutputTypeWindowsEventLog 0x7765766CU // 'wevl' - 1st param = C-string name, 2nd param = HMODULE or NULL. // Console meta output kind - Any kind of Console output (in horizontal order of preference): -// +// // Mac OS X = ANSI printf (viewable in Console.app) // Mac OS X Kernel = IOLog (/var/log/system.log) or kprintf (serial). // Windows = ANSI printf (Console window) or OutputDebugString (debugger). // Other = ANSI printf (viewer varies). -#define kDebugOutputTypeMetaConsole 0x434F4E53U // 'CONS' - no params +#define kDebugOutputTypeMetaConsole 0x434F4E53U // 'CONS' - no params //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef DebugOutputTypeFlags - - @abstract Flags controlling how the output type is configured. - - @constant kDebugOutputTypeFlagsTypeMask Bit mask for the output type (e.g. stdout, stderr, file, etc.). - @constant kDebugOutputTypeFlagsStdOut fprintf should go to stdout. - @constant kDebugOutputTypeFlagsStdErr fprintf should go to stderr. - @constant kDebugOutputTypeFlagsFile fprintf should go to a specific file (filename passed as va_arg). -*/ -typedef unsigned int DebugOutputTypeFlags; + @abstract Flags controlling how the output type is configured. -#define kDebugOutputTypeFlagsTypeMask 0xF -#define kDebugOutputTypeFlagsStdOut 1 -#define kDebugOutputTypeFlagsStdErr 2 -#define kDebugOutputTypeFlagsFile 10 + @constant kDebugOutputTypeFlagsTypeMask Bit mask for the output type (e.g. stdout, stderr, file, etc.). + @constant kDebugOutputTypeFlagsStdOut fprintf should go to stdout. + @constant kDebugOutputTypeFlagsStdErr fprintf should go to stderr. + @constant kDebugOutputTypeFlagsFile fprintf should go to a specific file (filename passed as va_arg). + */ + +typedef unsigned int DebugOutputTypeFlags; + +#define kDebugOutputTypeFlagsTypeMask 0xF +#define kDebugOutputTypeFlagsStdOut 1 +#define kDebugOutputTypeFlagsStdErr 2 +#define kDebugOutputTypeFlagsFile 10 //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef DebugOutputFunctionPtr - - @abstract Function ptr for a custom callback to print debug output. -*/ + + @abstract Function ptr for a custom callback to print debug output. + */ typedef void ( *DebugOutputFunctionPtr )( char *inData, size_t inSize, void *inContext ); @@ -221,48 +221,48 @@ typedef void ( *DebugOutputFunctionPtr )( char *inData, size_t inSize, void *inC //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef DebugFlags - - @abstract Flags controlling how output is printed. -*/ -typedef uint32_t DebugFlags; + @abstract Flags controlling how output is printed. + */ -#define kDebugFlagsNone 0 -#define kDebugFlagsNoAddress ( 1 << 0 ) -#define kDebugFlagsNoOffset ( 1 << 1 ) -#define kDebugFlags32BitOffset ( 1 << 2 ) -#define kDebugFlagsNoASCII ( 1 << 3 ) -#define kDebugFlagsNoNewLine ( 1 << 4 ) -#define kDebugFlags8BitSeparator ( 1 << 5 ) -#define kDebugFlags16BitSeparator ( 1 << 6 ) -#define kDebugFlagsNo32BitSeparator ( 1 << 7 ) -#define kDebugFlagsNo16ByteHexPad ( 1 << 8 ) -#define kDebugFlagsNoByteCount ( 1 << 9 ) +typedef uint32_t DebugFlags; + +#define kDebugFlagsNone 0 +#define kDebugFlagsNoAddress ( 1 << 0 ) +#define kDebugFlagsNoOffset ( 1 << 1 ) +#define kDebugFlags32BitOffset ( 1 << 2 ) +#define kDebugFlagsNoASCII ( 1 << 3 ) +#define kDebugFlagsNoNewLine ( 1 << 4 ) +#define kDebugFlags8BitSeparator ( 1 << 5 ) +#define kDebugFlags16BitSeparator ( 1 << 6 ) +#define kDebugFlagsNo32BitSeparator ( 1 << 7 ) +#define kDebugFlagsNo16ByteHexPad ( 1 << 8 ) +#define kDebugFlagsNoByteCount ( 1 << 9 ) //--------------------------------------------------------------------------------------------------------------------------- /*! @enum DebugTaskLevelFlags - - @abstract Flags indicating the task level. -*/ + + @abstract Flags indicating the task level. + */ enum { - kDebugInterruptLevelShift = 0, - kDebugInterruptLevelMask = 0x00000007, - kDebugInVBLTaskMask = 0x00000010, - kDebugInDeferredTaskMask = 0x00000020, - kDebugInSecondaryInterruptHandlerMask = 0x00000040, - kDebugPageFaultFatalMask = 0x00000100, // There should be a "kPageFaultFatalMask" in Debugging.h. - kDebugMPTaskLevelMask = 0x00000200, // There should be a "kMPTaskLevelMask" in Debugging.h. - kDebugInterruptDepthShift = 16, - kDebugInterruptDepthMask = 0x00FF0000 + kDebugInterruptLevelShift = 0, + kDebugInterruptLevelMask = 0x00000007, + kDebugInVBLTaskMask = 0x00000010, + kDebugInDeferredTaskMask = 0x00000020, + kDebugInSecondaryInterruptHandlerMask = 0x00000040, + kDebugPageFaultFatalMask = 0x00000100, // There should be a "kPageFaultFatalMask" in Debugging.h. + kDebugMPTaskLevelMask = 0x00000200, // There should be a "kMPTaskLevelMask" in Debugging.h. + kDebugInterruptDepthShift = 16, + kDebugInterruptDepthMask = 0x00FF0000 }; -#define DebugExtractTaskLevelInterruptLevel( LEVEL ) \ - ( ( ( LEVEL ) & kDebugInterruptLevelMask ) >> kDebugInterruptLevelShift ) - -#define DebugExtractTaskLevelInterruptDepth( LEVEL ) \ - ( ( ( LEVEL ) & kDebugInterruptDepthMask ) >> kDebugInterruptDepthShift ) +#define DebugExtractTaskLevelInterruptLevel( LEVEL ) \ + ( ( ( LEVEL ) &kDebugInterruptLevelMask ) >> kDebugInterruptLevelShift ) + +#define DebugExtractTaskLevelInterruptDepth( LEVEL ) \ + ( ( ( LEVEL ) &kDebugInterruptDepthMask ) >> kDebugInterruptDepthShift ) #if 0 #pragma mark == Levels == @@ -274,60 +274,60 @@ enum //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef DebugLevel - - @abstract Level used to control debug logging. -*/ -typedef int32_t DebugLevel; + @abstract Level used to control debug logging. + */ + +typedef int32_t DebugLevel; // Levels -#define kDebugLevelMask 0x0000FFFF -#define kDebugLevelChatty 100 -#define kDebugLevelVerbose 500 -#define kDebugLevelTrace 800 -#define kDebugLevelInfo 1000 -#define kDebugLevelNotice 3000 -#define kDebugLevelWarning 5000 -#define kDebugLevelAssert 6000 -#define kDebugLevelRequire 7000 -#define kDebugLevelError 8000 -#define kDebugLevelCritical 9000 -#define kDebugLevelAlert 10000 -#define kDebugLevelEmergency 11000 -#define kDebugLevelTragic 12000 -#define kDebugLevelMax 0x0000FFFF +#define kDebugLevelMask 0x0000FFFF +#define kDebugLevelChatty 100 +#define kDebugLevelVerbose 500 +#define kDebugLevelTrace 800 +#define kDebugLevelInfo 1000 +#define kDebugLevelNotice 3000 +#define kDebugLevelWarning 5000 +#define kDebugLevelAssert 6000 +#define kDebugLevelRequire 7000 +#define kDebugLevelError 8000 +#define kDebugLevelCritical 9000 +#define kDebugLevelAlert 10000 +#define kDebugLevelEmergency 11000 +#define kDebugLevelTragic 12000 +#define kDebugLevelMax 0x0000FFFF // Level Flags - -#define kDebugLevelFlagMask 0xFFFF0000 -#define kDebugLevelFlagStackTrace 0x00010000 -#define kDebugLevelFlagDebugBreak 0x00020000 + +#define kDebugLevelFlagMask 0xFFFF0000 +#define kDebugLevelFlagStackTrace 0x00010000 +#define kDebugLevelFlagDebugBreak 0x00020000 //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef LogLevel - - @abstract Level used to control which events are logged. -*/ -typedef int32_t LogLevel; + @abstract Level used to control which events are logged. + */ -#define kLogLevelUninitialized -1L -#define kLogLevelAll 0L -#define kLogLevelChatty 100L -#define kLogLevelVerbose 500L -#define kLogLevelTrace 800L -#define kLogLevelInfo 1000L -#define kLogLevelNotice 3000L -#define kLogLevelWarning 4000L -#define kLogLevelAssert 6000L -#define kLogLevelRequire 7000L -#define kLogLevelError 8000L -#define kLogLevelCritical 9000L -#define kLogLevelAlert 10000L -#define kLogLevelEmergency 11000L -#define kLogLevelTragic 12000L -#define kLogLevelOff 0x0000FFFEL +typedef int32_t LogLevel; + +#define kLogLevelUninitialized -1L +#define kLogLevelAll 0L +#define kLogLevelChatty 100L +#define kLogLevelVerbose 500L +#define kLogLevelTrace 800L +#define kLogLevelInfo 1000L +#define kLogLevelNotice 3000L +#define kLogLevelWarning 4000L +#define kLogLevelAssert 6000L +#define kLogLevelRequire 7000L +#define kLogLevelError 8000L +#define kLogLevelCritical 9000L +#define kLogLevelAlert 10000L +#define kLogLevelEmergency 11000L +#define kLogLevelTragic 12000L +#define kLogLevelOff 0x0000FFFEL #if 0 #pragma mark == Properties == @@ -335,140 +335,140 @@ typedef int32_t LogLevel; //--------------------------------------------------------------------------------------------------------------------------- /*! @typedef DebugPropertyTag - - @abstract Tag for properties. -*/ -typedef uint32_t DebugPropertyTag; + @abstract Tag for properties. + */ -#define kDebugPropertyTagPrintLevelMin 0x6D696E70U // 'minp' Get: 1st param = DebugLevel * - // Set: 1st param = DebugLevel +typedef uint32_t DebugPropertyTag; -#define kDebugPropertyTagPrintLevel kDebugPropertyTagPrintLevelMin +#define kDebugPropertyTagPrintLevelMin 0x6D696E70U // 'minp' Get: 1st param = DebugLevel * + // Set: 1st param = DebugLevel -#define kDebugPropertyTagPrintLevelMax 0x706D786CU // 'maxp' Get: 1st param = DebugLevel * - // Set: 1st param = DebugLevel +#define kDebugPropertyTagPrintLevel kDebugPropertyTagPrintLevelMin -#define kDebugPropertyTagBreakLevel 0x62726B6CU // 'brkl' Get: 1st param = DebugLevel * - // Set: 1st param = DebugLevel +#define kDebugPropertyTagPrintLevelMax 0x706D786CU // 'maxp' Get: 1st param = DebugLevel * + // Set: 1st param = DebugLevel + +#define kDebugPropertyTagBreakLevel 0x62726B6CU // 'brkl' Get: 1st param = DebugLevel * + // Set: 1st param = DebugLevel #if 0 #pragma mark == General macros == #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_UNUSED - - @abstract Macro to mark a paramter as unused to avoid unused parameter warnings. - - @discussion - - There is no universally supported pragma/attribute for indicating a variable is unused. DEBUG_UNUSED lets us - indicate a variable is unused in a manner that is supported by most compilers. -*/ -#define DEBUG_UNUSED( X ) (void)( X ) + @abstract Macro to mark a paramter as unused to avoid unused parameter warnings. + + @discussion + + There is no universally supported pragma/attribute for indicating a variable is unused. DEBUG_UNUSED lets us + indicate a variable is unused in a manner that is supported by most compilers. + */ + +#define DEBUG_UNUSED( X ) (void)( X ) //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_USE_ONLY - - @abstract Macro to mark a variable as used only when debugging is enabled. - - @discussion - - Variables are sometimes needed only for debugging. When debugging is turned off, these debug-only variables generate - compiler warnings about unused variables. To eliminate these warnings, use these macros to indicate variables that - are only used for debugging. -*/ -#if( DEBUG ) - #define DEBUG_USE_ONLY( X ) + @abstract Macro to mark a variable as used only when debugging is enabled. + + @discussion + + Variables are sometimes needed only for debugging. When debugging is turned off, these debug-only variables generate + compiler warnings about unused variables. To eliminate these warnings, use these macros to indicate variables that + are only used for debugging. + */ + +#if ( DEBUG ) + #define DEBUG_USE_ONLY( X ) #else - #define DEBUG_USE_ONLY( X ) (void)( X ) + #define DEBUG_USE_ONLY( X ) (void)( X ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_LOCAL - - @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. - - @discussion - - Rather than using "static" directly, using this macros allows you to access these variables external while - debugging without being penalized for production builds. -*/ -#if( DEBUG ) - #define DEBUG_LOCAL + @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. + + @discussion + + Rather than using "static" directly, using this macros allows you to access these variables external while + debugging without being penalized for production builds. + */ + +#if ( DEBUG ) + #define DEBUG_LOCAL #else - #define DEBUG_LOCAL static + #define DEBUG_LOCAL static #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_STATIC - - @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. - - @discussion - - Rather than using "static" directly, using this macros allows you to access these variables external while - debugging without being penalized for production builds. -*/ -#if( DEBUG ) - #define DEBUG_STATIC + @abstract Macros to make variables and functions static when debugging is off, but extern when debugging is on. + + @discussion + + Rather than using "static" directly, using this macros allows you to access these variables external while + debugging without being penalized for production builds. + */ + +#if ( DEBUG ) + #define DEBUG_STATIC #else - #define DEBUG_STATIC static + #define DEBUG_STATIC static #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DEBUG_EXPORT - - @abstract Macros to export variables. - - @discussion - - "__private_extern__" is a hack for IOKit to allow symbols to be exported from compilation units, but - // not exported outside a driver (IOKit uses a lame global namespace for symbols). This still does not - // solve the problem of multiple drivers in the same dependency chain since they share symbols. -*/ -#if( TARGET_API_MAC_OSX_KERNEL ) - #define DEBUG_EXPORT __private_extern__ + @abstract Macros to export variables. + + @discussion + + "__private_extern__" is a hack for IOKit to allow symbols to be exported from compilation units, but + // not exported outside a driver (IOKit uses a lame global namespace for symbols). This still does not + // solve the problem of multiple drivers in the same dependency chain since they share symbols. + */ + +#if ( TARGET_API_MAC_OSX_KERNEL ) + #define DEBUG_EXPORT __private_extern__ #else - #define DEBUG_EXPORT extern + #define DEBUG_EXPORT extern #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined debug_add - - @abstract Macro to add (or subtract if negative) a value when debugging is on. Does nothing if debugging is off. -*/ -#if( DEBUG ) - #define debug_add( A, B ) ( A ) += ( B ) + @abstract Macro to add (or subtract if negative) a value when debugging is on. Does nothing if debugging is off. + */ + +#if ( DEBUG ) + #define debug_add( A, B ) ( A ) += ( B ) #else - #define debug_add( A, B ) + #define debug_add( A, B ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined debug_perform - - @abstract Macro to perform something in debug-only builds. -*/ -#if( DEBUG ) - #define debug_perform( X ) do { X; } while( 0 ) + @abstract Macro to perform something in debug-only builds. + */ + +#if ( DEBUG ) + #define debug_perform( X ) do { X; } while( 0 ) #else - #define debug_perform( X ) + #define debug_perform( X ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function translate_errno - @abstract Returns 0 if the test success. If the test fails, returns errno if non-zero and othewise the alternate error. -*/ + @abstract Returns 0 if the test success. If the test fails, returns errno if non-zero and othewise the alternate error. + */ -#define translate_errno( TEST, ERRNO, ALTERNATE_ERROR ) ( ( TEST ) ? 0 : ( ERRNO ) ? ( ERRNO ) : ( ALTERNATE_ERROR ) ) +#define translate_errno( TEST, ERRNO, ALTERNATE_ERROR ) ( ( TEST ) ? 0 : ( ERRNO ) ? ( ERRNO ) : ( ALTERNATE_ERROR ) ) #if 0 #pragma mark == Compile Time macros == @@ -476,58 +476,58 @@ typedef uint32_t DebugPropertyTag; //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_compile_time - - @abstract Performs a compile-time check of something such as the size of an int. - - @discussion - - This declares an array with a size that is determined by a compile-time expression. If the expression evaluates - to 0, the array has a size of -1, which is illegal and generates a compile-time error. - - For example: - - check_compile_time( sizeof( int ) == 4 ); - - Note: This only works with compile-time expressions. - Note: This only works in places where extern declarations are allowed (e.g. global scope). - - References: - - - - - Note: The following macros differ from the macros on the www.jaggersoft.com web site because those versions do not - work with GCC due to GCC allow a zero-length array. Using a -1 condition turned out to be more portable. -*/ -#define check_compile_time( X ) extern int debug_compile_time_name[ ( X ) ? 1 : -1 ] + @abstract Performs a compile-time check of something such as the size of an int. + + @discussion + + This declares an array with a size that is determined by a compile-time expression. If the expression evaluates + to 0, the array has a size of -1, which is illegal and generates a compile-time error. + + For example: + + check_compile_time( sizeof( int ) == 4 ); + + Note: This only works with compile-time expressions. + Note: This only works in places where extern declarations are allowed (e.g. global scope). + + References: + + + + + Note: The following macros differ from the macros on the www.jaggersoft.com web site because those versions do not + work with GCC due to GCC allow a zero-length array. Using a -1 condition turned out to be more portable. + */ + +#define check_compile_time( X ) extern int debug_compile_time_name[ ( X ) ? 1 : -1 ] //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_compile_time_code - - @abstract Perform a compile-time check, suitable for placement in code, of something such as the size of an int. - - @discussion - - This creates a switch statement with an existing case for 0 and an additional case using the result of a - compile-time expression. A switch statement cannot have two case labels with the same constant so if the - compile-time expression evaluates to 0, it is illegal and generates a compile-time error. If the compile-time - expression does not evaluate to 0, the resulting value is used as the case label and it compiles without error. - For example: - - check_compile_time_code( sizeof( int ) == 4 ); - - Note: This only works with compile-time expressions. - Note: This does not work in a global scope so it must be inside a function. - - References: - - - -*/ + @abstract Perform a compile-time check, suitable for placement in code, of something such as the size of an int. -#define check_compile_time_code( X ) switch( 0 ) { case 0: case X:; } + @discussion + + This creates a switch statement with an existing case for 0 and an additional case using the result of a + compile-time expression. A switch statement cannot have two case labels with the same constant so if the + compile-time expression evaluates to 0, it is illegal and generates a compile-time error. If the compile-time + expression does not evaluate to 0, the resulting value is used as the case label and it compiles without error. + + For example: + + check_compile_time_code( sizeof( int ) == 4 ); + + Note: This only works with compile-time expressions. + Note: This does not work in a global scope so it must be inside a function. + + References: + + + + */ + +#define check_compile_time_code( X ) switch( 0 ) { case 0: case X:; } #if 0 #pragma mark == check macros == @@ -535,182 +535,182 @@ typedef uint32_t DebugPropertyTag; //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check - - @abstract Check that an expression is true (non-zero). - - @discussion - - If expression evalulates to false, this prints debugging information (actual expression string, file, line number, - function name, etc.) using the default debugging output method. - - Code inside check() statements is not compiled into production builds. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef check + @abstract Check that an expression is true (non-zero). + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method. + + Code inside check() statements is not compiled into production builds. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check #endif -#if( !defined( check ) ) - #if( DEBUG ) - #define check( X ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - } \ - } while( 0 ) - #else - #define check( X ) - #endif +#if ( !defined( check ) ) + #if ( DEBUG ) + #define check( X ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + } while( 0 ) + #else + #define check( X ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_string - - @abstract Check that an expression is true (non-zero) with an explanation. - - @discussion - - If expression evalulates to false, this prints debugging information (actual expression string, file, line number, - function name, etc.) and a custom explanation string using the default debugging output method. - - Code inside check_string() statements is not compiled into production builds. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef check_string + @abstract Check that an expression is true (non-zero) with an explanation. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method. + + Code inside check_string() statements is not compiled into production builds. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check_string #endif -#if( !defined( check_string ) ) - #if( DEBUG ) - #define check_string( X, STR ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - } \ - \ - } while( 0 ) - #else - #define check_string( X, STR ) - #endif +#if ( !defined( check_string ) ) + #if ( DEBUG ) + #define check_string( X, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_string( X, STR ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_noerr - - @abstract Check that an error code is noErr (0). - - @discussion - - If the error code is non-0, this prints debugging information (actual expression string, file, line number, - function name, etc.) using the default debugging output method. - - Code inside check_noerr() statements is not compiled into production builds. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef check_noerr + @abstract Check that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method. + + Code inside check_noerr() statements is not compiled into production builds. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check_noerr #endif -#if( !defined( check_noerr ) ) - #if( DEBUG ) - #define check_noerr( ERR ) \ - do \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERR ); \ - if( localErr != 0 ) \ - { \ - debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - } \ - \ - } while( 0 ) - #else - #define check_noerr( ERR ) - #endif +#if ( !defined( check_noerr ) ) + #if ( DEBUG ) + #define check_noerr( ERR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_noerr( ERR ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_noerr_string - - @abstract Check that an error code is noErr (0) with an explanation. - - @discussion - - If the error code is non-0, this prints debugging information (actual expression string, file, line number, - function name, etc.) and a custom explanation string using the default debugging output method. - - Code inside check_noerr_string() statements is not compiled into production builds. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef check_noerr_string + @abstract Check that an error code is noErr (0) with an explanation. + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method. + + Code inside check_noerr_string() statements is not compiled into production builds. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef check_noerr_string #endif -#if( !defined( check_noerr_string ) ) - #if( DEBUG ) - #define check_noerr_string( ERR, STR ) \ - do \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERR ); \ - if( localErr != 0 ) \ - { \ - debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - } \ - \ - } while( 0 ) - #else - #define check_noerr_string( ERR, STR ) - #endif +#if ( !defined( check_noerr_string ) ) + #if ( DEBUG ) + #define check_noerr_string( ERR, STR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_noerr_string( ERR, STR ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_translated_errno - - @abstract Check a condition and prints errno (if non-zero) to the log. - - @discussion - - Code inside check_translated_errno() statements is not compiled into production builds. -*/ -#if( !defined( check_translated_errno ) ) - #if( DEBUG ) - #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) \ - do \ - { \ - if( !( TEST ) ) \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERRNO ); \ - localErr = ( localErr != 0 ) ? localErr : (int_least32_t)( ALTERNATE_ERROR ); \ - debug_print_assert( localErr, #TEST, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - } \ - \ - } while( 0 ) - #else - #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) - #endif + @abstract Check a condition and prints errno (if non-zero) to the log. + + @discussion + + Code inside check_translated_errno() statements is not compiled into production builds. + */ + +#if ( !defined( check_translated_errno ) ) + #if ( DEBUG ) + #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) \ + do \ + { \ + if( !( TEST ) ) \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERRNO ); \ + localErr = ( localErr != 0 ) ? localErr : (int_least32_t)( ALTERNATE_ERROR ); \ + debug_print_assert( localErr, # TEST, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + } \ + \ + } while( 0 ) + #else + #define check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined check_ptr_overlap - - @abstract Checks that two ptrs do not overlap. -*/ -#define check_ptr_overlap( P1, P1_SIZE, P2, P2_SIZE ) \ - do \ - { \ - check( !( ( (uintptr_t)( P1 ) >= (uintptr_t)( P2 ) ) && \ - ( (uintptr_t)( P1 ) < ( ( (uintptr_t)( P2 ) ) + ( P2_SIZE ) ) ) ) ); \ - check( !( ( (uintptr_t)( P2 ) >= (uintptr_t)( P1 ) ) && \ - ( (uintptr_t)( P2 ) < ( ( (uintptr_t)( P1 ) ) + ( P1_SIZE ) ) ) ) ); \ - \ - } while( 0 ) + @abstract Checks that two ptrs do not overlap. + */ + +#define check_ptr_overlap( P1, P1_SIZE, P2, P2_SIZE ) \ + do \ + { \ + check( !( ( (uintptr_t)( P1 ) >= (uintptr_t)( P2 ) ) && \ + ( (uintptr_t)( P1 ) < ( ( (uintptr_t)( P2 ) ) + ( P2_SIZE ) ) ) ) ); \ + check( !( ( (uintptr_t)( P2 ) >= (uintptr_t)( P1 ) ) && \ + ( (uintptr_t)( P2 ) < ( ( (uintptr_t)( P1 ) ) + ( P1_SIZE ) ) ) ) ); \ + \ + } while( 0 ) #if 0 #pragma mark == require macros == @@ -718,364 +718,364 @@ typedef uint32_t DebugPropertyTag; //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require - - @abstract Requires that an expression evaluate to true. - - @discussion - - If expression evalulates to false, this prints debugging information (actual expression string, file, line number, - function name, etc.) using the default debugging output method then jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require + @abstract Requires that an expression evaluate to true. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require #endif -#if( !defined( require ) ) - #define require( X, LABEL ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require ) ) + #define require( X, LABEL ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_string - - @abstract Requires that an expression evaluate to true with an explanation. - - @discussion - - If expression evalulates to false, this prints debugging information (actual expression string, file, line number, - function name, etc.) and a custom explanation string using the default debugging output method then jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_string + @abstract Requires that an expression evaluate to true with an explanation. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method then jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_string #endif -#if( !defined( require_string ) ) - #define require_string( X, LABEL, STR ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_string ) ) + #define require_string( X, LABEL, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_quiet - - @abstract Requires that an expression evaluate to true. - - @discussion - - If expression evalulates to false, this jumps to a label. No debugging information is printed. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_quiet + @abstract Requires that an expression evaluate to true. + + @discussion + + If expression evalulates to false, this jumps to a label. No debugging information is printed. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_quiet #endif -#if( !defined( require_quiet ) ) - #define require_quiet( X, LABEL ) \ - do \ - { \ - if( !( X ) ) \ - { \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_quiet ) ) + #define require_quiet( X, LABEL ) \ + do \ + { \ + if( !( X ) ) \ + { \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_noerr - - @abstract Require that an error code is noErr (0). - - @discussion - - If the error code is non-0, this prints debugging information (actual expression string, file, line number, - function name, etc.) using the default debugging output method then jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_noerr + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr #endif -#if( !defined( require_noerr ) ) - #define require_noerr( ERR, LABEL ) \ - do \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERR ); \ - if( localErr != 0 ) \ - { \ - debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_noerr ) ) + #define require_noerr( ERR, LABEL ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_noerr_string - - @abstract Require that an error code is noErr (0). - - @discussion - - If the error code is non-0, this prints debugging information (actual expression string, file, line number, - function name, etc.), and a custom explanation string using the default debugging output method using the - default debugging output method then jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_noerr_string + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.), and a custom explanation string using the default debugging output method using the + default debugging output method then jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_string #endif -#if( !defined( require_noerr_string ) ) - #define require_noerr_string( ERR, LABEL, STR ) \ - do \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERR ); \ - if( localErr != 0 ) \ - { \ - debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_noerr_string ) ) + #define require_noerr_string( ERR, LABEL, STR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_noerr_action_string - - @abstract Require that an error code is noErr (0). - - @discussion - - If the error code is non-0, this prints debugging information (actual expression string, file, line number, - function name, etc.), and a custom explanation string using the default debugging output method using the - default debugging output method then executes an action and jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_noerr_action_string + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.), and a custom explanation string using the default debugging output method using the + default debugging output method then executes an action and jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_action_string #endif -#if( !defined( require_noerr_action_string ) ) - #define require_noerr_action_string( ERR, LABEL, ACTION, STR ) \ - do \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERR ); \ - if( localErr != 0 ) \ - { \ - debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - { ACTION; } \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_noerr_action_string ) ) + #define require_noerr_action_string( ERR, LABEL, ACTION, STR ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_noerr_quiet - - @abstract Require that an error code is noErr (0). - - @discussion - - If the error code is non-0, this jumps to a label. No debugging information is printed. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_noerr_quiet + @abstract Require that an error code is noErr (0). + + @discussion + + If the error code is non-0, this jumps to a label. No debugging information is printed. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_quiet #endif -#if( !defined( require_noerr_quiet ) ) - #define require_noerr_quiet( ERR, LABEL ) \ - do \ - { \ - if( ( ERR ) != 0 ) \ - { \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_noerr_quiet ) ) + #define require_noerr_quiet( ERR, LABEL ) \ + do \ + { \ + if( ( ERR ) != 0 ) \ + { \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_noerr_action - - @abstract Require that an error code is noErr (0) with an action to execute otherwise. - - @discussion - - If the error code is non-0, this prints debugging information (actual expression string, file, line number, - function name, etc.) using the default debugging output method then executes an action and jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_noerr_action + @abstract Require that an error code is noErr (0) with an action to execute otherwise. + + @discussion + + If the error code is non-0, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then executes an action and jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_action #endif -#if( !defined( require_noerr_action ) ) - #define require_noerr_action( ERR, LABEL, ACTION ) \ - do \ - { \ - int_least32_t localErr; \ - \ - localErr = (int_least32_t)( ERR ); \ - if( localErr != 0 ) \ - { \ - debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - { ACTION; } \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_noerr_action ) ) + #define require_noerr_action( ERR, LABEL, ACTION ) \ + do \ + { \ + int_least32_t localErr; \ + \ + localErr = (int_least32_t)( ERR ); \ + if( localErr != 0 ) \ + { \ + debug_print_assert( localErr, NULL, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_noerr_action_quiet - - @abstract Require that an error code is noErr (0) with an action to execute otherwise. - - @discussion - - If the error code is non-0, this executes an action and jumps to a label. No debugging information is printed. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_noerr_action_quiet + @abstract Require that an error code is noErr (0) with an action to execute otherwise. + + @discussion + + If the error code is non-0, this executes an action and jumps to a label. No debugging information is printed. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_noerr_action_quiet #endif -#if( !defined( require_noerr_action_quiet ) ) - #define require_noerr_action_quiet( ERR, LABEL, ACTION ) \ - do \ - { \ - if( ( ERR ) != 0 ) \ - { \ - { ACTION; } \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_noerr_action_quiet ) ) + #define require_noerr_action_quiet( ERR, LABEL, ACTION ) \ + do \ + { \ + if( ( ERR ) != 0 ) \ + { \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_action - - @abstract Requires that an expression evaluate to true with an action to execute otherwise. - - @discussion - - If expression evalulates to false, this prints debugging information (actual expression string, file, line number, - function name, etc.) using the default debugging output method then executes an action and jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_action + @abstract Requires that an expression evaluate to true with an action to execute otherwise. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) using the default debugging output method then executes an action and jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_action #endif -#if( !defined( require_action ) ) - #define require_action( X, LABEL, ACTION ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - { ACTION; } \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_action ) ) + #define require_action( X, LABEL, ACTION ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_action_quiet - - @abstract Requires that an expression evaluate to true with an action to execute otherwise. - - @discussion - - If expression evalulates to false, this executes an action and jumps to a label. No debugging information is printed. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_action_quiet + @abstract Requires that an expression evaluate to true with an action to execute otherwise. + + @discussion + + If expression evalulates to false, this executes an action and jumps to a label. No debugging information is printed. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_action_quiet #endif -#if( !defined( require_action_quiet ) ) - #define require_action_quiet( X, LABEL, ACTION ) \ - do \ - { \ - if( !( X ) ) \ - { \ - { ACTION; } \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_action_quiet ) ) + #define require_action_quiet( X, LABEL, ACTION ) \ + do \ + { \ + if( !( X ) ) \ + { \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_action_string - - @abstract Requires that an expression evaluate to true with an explanation and action to execute otherwise. - - @discussion - - If expression evalulates to false, this prints debugging information (actual expression string, file, line number, - function name, etc.) and a custom explanation string using the default debugging output method then executes an - action and jumps to a label. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef require_action_string + @abstract Requires that an expression evaluate to true with an explanation and action to execute otherwise. + + @discussion + + If expression evalulates to false, this prints debugging information (actual expression string, file, line number, + function name, etc.) and a custom explanation string using the default debugging output method then executes an + action and jumps to a label. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef require_action_string #endif -#if( !defined( require_action_string ) ) - #define require_action_string( X, LABEL, ACTION, STR ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - { ACTION; } \ - goto LABEL; \ - } \ - \ - } while( 0 ) +#if ( !defined( require_action_string ) ) + #define require_action_string( X, LABEL, ACTION, STR ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + { ACTION; } \ + goto LABEL; \ + } \ + \ + } while( 0 ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined require_throw - - @abstract Requires that an expression evaluates to true or an exception is thrown. - - @discussion - - If the expression evaluates to false, this prints debugging information (actual expression string, file, - line number, function name, etc.) using the default debugging output method then throws an exception. -*/ -#if( defined( __cplusplus ) ) - #define require_throw( X ) \ - do \ - { \ - if( !( X ) ) \ - { \ - debug_print_assert( 0, #X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ - throw kUnknownErr; \ - } \ - \ - } while( 0 ) + @abstract Requires that an expression evaluates to true or an exception is thrown. + + @discussion + + If the expression evaluates to false, this prints debugging information (actual expression string, file, + line number, function name, etc.) using the default debugging output method then throws an exception. + */ + +#if ( defined( __cplusplus ) ) + #define require_throw( X ) \ + do \ + { \ + if( !( X ) ) \ + { \ + debug_print_assert( 0, # X, NULL, __FILE__, __LINE__, __ROUTINE__ ); \ + throw kUnknownErr; \ + } \ + \ + } while( 0 ) #endif #if 0 @@ -1086,11 +1086,11 @@ typedef uint32_t DebugPropertyTag; // Design-By-Contract macros //=========================================================================================================================== -#define ensure( X ) check( X ) -#define ensure_string( X, STR ) check_string( X, STR ) -#define ensure_noerr( ERR ) check_noerr( ERR ) -#define ensure_noerr_string( ERR, STR ) check_noerr_string( ERR, STR ) -#define ensure_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) +#define ensure( X ) check( X ) +#define ensure_string( X, STR ) check_string( X, STR ) +#define ensure_noerr( ERR ) check_noerr( ERR ) +#define ensure_noerr_string( ERR, STR ) check_noerr_string( ERR, STR ) +#define ensure_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) check_translated_errno( TEST, ERRNO, ALTERNATE_ERROR ) // Note: Design-By-Contract "require" macros are already defined elsewhere. @@ -1102,37 +1102,37 @@ typedef uint32_t DebugPropertyTag; // Expect macros //=========================================================================================================================== -// Expect macros allow code to include runtime checking of things that should not happen in shipping code (e.g. internal -// programmer errors, such as a NULL parameter where it is not allowed). Once the code has been verified to work correctly -// without asserting, the DEBUG_EXPECT_VERIFIED conditional can be set to eliminate the error checking entirely. It can +// Expect macros allow code to include runtime checking of things that should not happen in shipping code (e.g. internal +// programmer errors, such as a NULL parameter where it is not allowed). Once the code has been verified to work correctly +// without asserting, the DEBUG_EXPECT_VERIFIED conditional can be set to eliminate the error checking entirely. It can // also be useful to measure the cost of error checking code by profiling with it enable and with it disabled. -#if( DEBUG_EXPECT_VERIFIED ) - #define require_expect - #define require_string_expect - #define require_quiet_expect - #define require_noerr_expect - #define require_noerr_string_expect - #define require_noerr_action_string_expect - #define require_noerr_quiet_expect - #define require_noerr_action_expect - #define require_noerr_action_quiet_expect - #define require_action_expect - #define require_action_quiet_expect - #define require_action_string_expect +#if ( DEBUG_EXPECT_VERIFIED ) + #define require_expect + #define require_string_expect + #define require_quiet_expect + #define require_noerr_expect + #define require_noerr_string_expect + #define require_noerr_action_string_expect + #define require_noerr_quiet_expect + #define require_noerr_action_expect + #define require_noerr_action_quiet_expect + #define require_action_expect + #define require_action_quiet_expect + #define require_action_string_expect #else - #define require_expect require - #define require_string_expect require_string - #define require_quiet_expect require_quiet - #define require_noerr_expect require_noerr - #define require_noerr_string_expect require_noerr_string - #define require_noerr_action_string_expect require_noerr_action_string - #define require_noerr_quiet_expect require_noerr_quiet - #define require_noerr_action_expect require_noerr_action - #define require_noerr_action_quiet_expect require_noerr_action_quiet - #define require_action_expect require_action - #define require_action_quiet_expect require_action_quiet - #define require_action_string_expect require_action_string + #define require_expect require + #define require_string_expect require_string + #define require_quiet_expect require_quiet + #define require_noerr_expect require_noerr + #define require_noerr_string_expect require_noerr_string + #define require_noerr_action_string_expect require_noerr_action_string + #define require_noerr_quiet_expect require_noerr_quiet + #define require_noerr_action_expect require_noerr_action + #define require_noerr_action_quiet_expect require_noerr_action_quiet + #define require_action_expect require_action + #define require_action_quiet_expect require_action_quiet + #define require_action_string_expect require_action_string #endif #if 0 @@ -1141,245 +1141,245 @@ typedef uint32_t DebugPropertyTag; //--------------------------------------------------------------------------------------------------------------------------- /*! @defined debug_string - - @abstract Prints a debugging C string. -*/ -#if( DEBUG_OVERRIDE_APPLE_MACROS ) - #undef debug_string + @abstract Prints a debugging C string. + */ + +#if ( DEBUG_OVERRIDE_APPLE_MACROS ) + #undef debug_string #endif -#if( !defined( debug_string ) ) - #if( DEBUG ) - #define debug_string( STR ) \ - do \ - { \ - debug_print_assert( 0, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ - \ - } while( 0 ) - #else - #define debug_string( STR ) - #endif +#if ( !defined( debug_string ) ) + #if ( DEBUG ) + #define debug_string( STR ) \ + do \ + { \ + debug_print_assert( 0, NULL, STR, __FILE__, __LINE__, __ROUTINE__ ); \ + \ + } while( 0 ) + #else + #define debug_string( STR ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined debug_print_assert - - @abstract Prints an assertion. -*/ -#if( DEBUG ) - #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) \ - DebugPrintAssert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) + @abstract Prints an assertion. + */ + +#if ( DEBUG ) + #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) \ + DebugPrintAssert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) #else - #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) + #define debug_print_assert( ERROR_CODE, ASSERT_STRING, MESSAGE, FILENAME, LINE_NUMBER, FUNCTION ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined dlog - - @abstract Prints a debug-only message. -*/ -#if( DEBUG ) - #if( DEBUG_C99_VA_ARGS ) - #define dlog( ... ) DebugPrintF( __VA_ARGS__ ) - #elif( DEBUG_GNU_VA_ARGS ) - #define dlog( ARGS... ) DebugPrintF( ## ARGS ) - #else - #define dlog DebugPrintF - #endif + @abstract Prints a debug-only message. + */ + +#if ( DEBUG ) + #if ( DEBUG_C99_VA_ARGS ) + #define dlog(... ) DebugPrintF( __VA_ARGS__ ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define dlog( ARGS... ) DebugPrintF( ## ARGS ) + #else + #define dlog DebugPrintF + #endif #else - #if( DEBUG_C99_VA_ARGS ) - #define dlog( ... ) - #elif( DEBUG_GNU_VA_ARGS ) - #define dlog( ARGS... ) - #else - #define dlog while( 0 ) - #endif + #if ( DEBUG_C99_VA_ARGS ) + #define dlog(... ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define dlog( ARGS... ) + #else + #define dlog while( 0 ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined dlogv - - @abstract Prints a debug-only message. -*/ -#if( DEBUG ) - #define dlogv( LEVEL, FORMAT, LIST ) DebugPrintFVAList( ( LEVEL ), ( FORMAT ), ( LIST ) ) + @abstract Prints a debug-only message. + */ + +#if ( DEBUG ) + #define dlogv( LEVEL, FORMAT, LIST ) DebugPrintFVAList( ( LEVEL ), ( FORMAT ), ( LIST ) ) #else - #define dlogv( LEVEL, FORMAT, LIST ) + #define dlogv( LEVEL, FORMAT, LIST ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined dlogmem - - @abstract Prints a debug-only dump of memory. -*/ -#if( DEBUG ) - #define dlogmem( LEVEL, PTR, SIZE ) \ - DebugHexDump( ( LEVEL ), 0, NULL, 0, 0, NULL, 0, ( PTR ), ( PTR ), ( SIZE ), kDebugFlagsNone, NULL, 0 ) + @abstract Prints a debug-only dump of memory. + */ + +#if ( DEBUG ) + #define dlogmem( LEVEL, PTR, SIZE ) \ + DebugHexDump( ( LEVEL ), 0, NULL, 0, 0, NULL, 0, ( PTR ), ( PTR ), ( SIZE ), kDebugFlagsNone, NULL, 0 ) #else - #define dlogmem( LEVEL, PTR, SIZE ) + #define dlogmem( LEVEL, PTR, SIZE ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DebugNSLog - - @abstract Debug-only macro for the Cocoa NSLog function. -*/ -#if( DEBUG ) - #if( DEBUG_C99_VA_ARGS ) - #define DebugNSLog( ... ) NSLog( __VA_ARGS__ ) - #elif( DEBUG_GNU_VA_ARGS ) - #define DebugNSLog( ARGS... ) NSLog( ## ARGS ) - #else - #define DebugNSLog NSLog - #endif + @abstract Debug-only macro for the Cocoa NSLog function. + */ + +#if ( DEBUG ) + #if ( DEBUG_C99_VA_ARGS ) + #define DebugNSLog(... ) NSLog( __VA_ARGS__ ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define DebugNSLog( ARGS... ) NSLog( ## ARGS ) + #else + #define DebugNSLog NSLog + #endif #else - #if( DEBUG_C99_VA_ARGS ) - #define DebugNSLog( ... ) - #elif( DEBUG_GNU_VA_ARGS ) - #define DebugNSLog( ARGS... ) - #else - #define DebugNSLog while( 0 ) - #endif + #if ( DEBUG_C99_VA_ARGS ) + #define DebugNSLog(... ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define DebugNSLog( ARGS... ) + #else + #define DebugNSLog while( 0 ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @defined DebugLogMsg - - @abstract Debug-only macro for the VxWorks logMsg function. -*/ -#if( TARGET_OS_VXWORKS ) - #if( DEBUG ) - #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) \ - do \ - { \ - if( ( inLevel >= gDebugPrintLevelMin ) || ( inLevel <= gDebugPrintLevelMax ) ) \ - { \ - logMsg( ( FORMAT ), ( P1 ), ( P2 ), ( P3 ), ( P4 ), ( P5 ), ( P6 ) ); \ - } \ - \ - } while( 0 ) - #else - #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) - #endif + @abstract Debug-only macro for the VxWorks logMsg function. + */ + +#if ( TARGET_OS_VXWORKS ) + #if ( DEBUG ) + #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) \ + do \ + { \ + if( ( inLevel >= gDebugPrintLevelMin ) || ( inLevel <= gDebugPrintLevelMax ) ) \ + { \ + logMsg( ( FORMAT ), ( P1 ), ( P2 ), ( P3 ), ( P4 ), ( P5 ), ( P6 ) ); \ + } \ + \ + } while( 0 ) + #else + #define DebugLogMsg( LEVEL, FORMAT, P1, P2, P3, P4, P5, P6 ) + #endif #else - #define DebugLogMsg dlog + #define DebugLogMsg dlog #endif #if 0 #pragma mark == Routines - General == #endif -#ifdef __cplusplus - extern "C" { +#ifdef __cplusplus +extern "C" { #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugInitialize - @abstract Initializes the debugging library for a specific kind of output. + @abstract Initializes the debugging library for a specific kind of output. - @param inType - @param varArg Variable number parameters, controlled by the "inType" parameter. -*/ + @param inType + @param varArg Variable number parameters, controlled by the "inType" parameter. + */ -#if( DEBUG ) - DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ); +#if ( DEBUG ) +DEBUG_EXPORT OSStatus DebugInitialize( DebugOutputType inType, ... ); #endif -#if( DEBUG ) - #if( DEBUG_C99_VA_ARGS ) - #define debug_initialize( ... ) DebugInitialize( __VA_ARGS__ ) - #elif( DEBUG_GNU_VA_ARGS ) - #define debug_initialize( ARGS... ) DebugInitialize( ## ARGS ) - #else - #define debug_initialize DebugInitialize - #endif +#if ( DEBUG ) + #if ( DEBUG_C99_VA_ARGS ) + #define debug_initialize(... ) DebugInitialize( __VA_ARGS__ ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define debug_initialize( ARGS... ) DebugInitialize( ## ARGS ) + #else + #define debug_initialize DebugInitialize + #endif #else - #if( DEBUG_C99_VA_ARGS ) - #define debug_initialize( ... ) - #elif( DEBUG_GNU_VA_ARGS ) - #define debug_initialize( ARGS... ) - #else - #define debug_initialize while( 0 ) - #endif + #if ( DEBUG_C99_VA_ARGS ) + #define debug_initialize(... ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define debug_initialize( ARGS... ) + #else + #define debug_initialize while( 0 ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugFinalize - @abstract Releases any resources used by the debugging library -*/ + @abstract Releases any resources used by the debugging library + */ -#if( DEBUG ) - DEBUG_EXPORT void DebugFinalize( void ); +#if ( DEBUG ) +DEBUG_EXPORT void DebugFinalize( void ); #endif -#if( DEBUG ) - #define debug_terminate() DebugFinalize() +#if ( DEBUG ) + #define debug_terminate() DebugFinalize() #else - #define debug_terminate() + #define debug_terminate() #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugGetProperty - @abstract Gets the specified property from the debugging library. -*/ + @abstract Gets the specified property from the debugging library. + */ -#if( DEBUG ) - DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ); +#if ( DEBUG ) +DEBUG_EXPORT OSStatus DebugGetProperty( DebugPropertyTag inTag, ... ); #endif -#if( DEBUG ) - #if( DEBUG_C99_VA_ARGS ) - #define debug_get_property( ... ) DebugGetProperty( __VA_ARGS__ ) - #elif( DEBUG_GNU_VA_ARGS ) - #define debug_get_property( ARGS... ) DebugGetProperty( ## ARGS ) - #else - #define debug_get_property DebugGetProperty - #endif +#if ( DEBUG ) + #if ( DEBUG_C99_VA_ARGS ) + #define debug_get_property(... ) DebugGetProperty( __VA_ARGS__ ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define debug_get_property( ARGS... ) DebugGetProperty( ## ARGS ) + #else + #define debug_get_property DebugGetProperty + #endif #else - #if( DEBUG_C99_VA_ARGS ) - #define debug_get_property( ... ) - #elif( DEBUG_GNU_VA_ARGS ) - #define debug_get_property( ARGS... ) - #else - #define debug_get_property while( 0 ) - #endif + #if ( DEBUG_C99_VA_ARGS ) + #define debug_get_property(... ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define debug_get_property( ARGS... ) + #else + #define debug_get_property while( 0 ) + #endif #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugSetProperty - @abstract Sets the specified property from the debugging library. -*/ + @abstract Sets the specified property from the debugging library. + */ -#if( DEBUG ) - DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ); +#if ( DEBUG ) +DEBUG_EXPORT OSStatus DebugSetProperty( DebugPropertyTag inTag, ... ); #endif -#if( DEBUG ) - #if( DEBUG_C99_VA_ARGS ) - #define debug_set_property( ... ) DebugSetProperty( __VA_ARGS__ ) - #elif( DEBUG_GNU_VA_ARGS ) - #define debug_set_property( ARGS... ) DebugSetProperty( ## ARGS ) - #else - #define debug_set_property DebugSetProperty - #endif +#if ( DEBUG ) + #if ( DEBUG_C99_VA_ARGS ) + #define debug_set_property(... ) DebugSetProperty( __VA_ARGS__ ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define debug_set_property( ARGS... ) DebugSetProperty( ## ARGS ) + #else + #define debug_set_property DebugSetProperty + #endif #else - #if( DEBUG_C99_VA_ARGS ) - #define debug_set_property( ... ) - #elif( DEBUG_GNU_VA_ARGS ) - #define debug_set_property( ARGS... ) - #else - #define debug_set_property while( 0 ) - #endif + #if ( DEBUG_C99_VA_ARGS ) + #define debug_set_property(... ) + #elif ( DEBUG_GNU_VA_ARGS ) + #define debug_set_property( ARGS... ) + #else + #define debug_set_property while( 0 ) + #endif #endif #if 0 @@ -1389,68 +1389,68 @@ typedef uint32_t DebugPropertyTag; //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugPrintF - @abstract Prints a debug message with printf-style formatting. - - @param inLevel Error that generated this assert or noErr. - - @param inFormatString - C string containing assertion text. + @abstract Prints a debug message with printf-style formatting. - @param VAR_ARG - Variable number of arguments depending on the format string. - - @result Number of bytes printed or -1 on error. -*/ + @param inLevel Error that generated this assert or noErr. -#if( DEBUG ) - DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ); + @param inFormatString + C string containing assertion text. + + @param VAR_ARG + Variable number of arguments depending on the format string. + + @result Number of bytes printed or -1 on error. + */ + +#if ( DEBUG ) +DEBUG_EXPORT size_t DebugPrintF( DebugLevel inLevel, const char *inFormat, ... ); #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugPrintFVAList - @abstract va_list version of DebugPrintF. See DebugPrintF for more info. -*/ + @abstract va_list version of DebugPrintF. See DebugPrintF for more info. + */ -#if( DEBUG ) - DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ); +#if ( DEBUG ) +DEBUG_EXPORT size_t DebugPrintFVAList( DebugLevel inLevel, const char *inFormat, va_list inArgs ); #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugPrintAssert - @abstract Prints a message describing the reason the (e.g. an assert failed), an optional error message, - an optional source filename, an optional source line number. + @abstract Prints a message describing the reason the (e.g. an assert failed), an optional error message, + an optional source filename, an optional source line number. - @param inErrorCode Error that generated this assert or noErr. - @param inAssertString C string containing assertion text. - @param inMessage C string containing a message about the assert. - @param inFileName C string containing path of file where the error occurred. - @param inLineNumber Line number in source file where the error occurred. - @param inFunction C string containing name of function where assert occurred. + @param inErrorCode Error that generated this assert or noErr. + @param inAssertString C string containing assertion text. + @param inMessage C string containing a message about the assert. + @param inFileName C string containing path of file where the error occurred. + @param inLineNumber Line number in source file where the error occurred. + @param inFunction C string containing name of function where assert occurred. - @discussion - - Example output: - - [ASSERT] assert: "dataPtr != NULL" allocate memory for object failed - [ASSERT] where: "MyFile.c", line 123, ("MyFunction") - - OR - - [ASSERT] error: -6728 (kNoMemoryErr) - [ASSERT] where: "MyFile.c", line 123, ("MyFunction") -*/ + @discussion -#if( DEBUG ) - DEBUG_EXPORT void - DebugPrintAssert( - int_least32_t inErrorCode, - const char * inAssertString, - const char * inMessage, - const char * inFilename, - int_least32_t inLineNumber, - const char * inFunction ); + Example output: + + [ASSERT] assert: "dataPtr != NULL" allocate memory for object failed + [ASSERT] where: "MyFile.c", line 123, ("MyFunction") + + OR + + [ASSERT] error: -6728 (kNoMemoryErr) + [ASSERT] where: "MyFile.c", line 123, ("MyFunction") + */ + +#if ( DEBUG ) +DEBUG_EXPORT void +DebugPrintAssert( + int_least32_t inErrorCode, + const char * inAssertString, + const char * inMessage, + const char * inFilename, + int_least32_t inLineNumber, + const char * inFunction ); #endif #if 0 @@ -1459,149 +1459,149 @@ typedef uint32_t DebugPropertyTag; //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugSNPrintF - - @abstract Debugging versions of standard C snprintf with extra features. - - @param sbuffer Buffer to receive result. Null terminated unless the buffer size is 0. - @param buflen Size of the buffer including space for the null terminator. - @param fmt printf-style format string. - @param VAR_ARG Variable number of arguments depending on the format string. - @result Number of characters written (minus the null terminator). - - @discussion - - Extra features over the standard C snprintf: -
-		64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb).
-		%@   - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription.
-		%a   - Network Address: %.4a=IPv4, %.6a=Ethernet, %.8a Fibre Channel, %.16a=IPv6. Arg=ptr to network address.
-		%#a  - IPv4 or IPv6 mDNSAddr. Arg=ptr to mDNSAddr.
-		%##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr.
-		%b   - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc.
-		%C   - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode.
-		%H   - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
-		%#H  - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
-		%m   - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code arg=the same as %d, %x, etc.
-		%#s  - Pascal-style length-prefixed string. Arg=ptr to string.
-		%##s - DNS label-sequence name. Arg=ptr to name.
-		%S   - UTF-16 string, 0x0000 terminated. Host order if no BOM. Precision is UTF-16 count. Precision includes BOM.
-		%#S  - Big Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
-		%##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
-		%U   - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID.
-	
-*/ + @abstract Debugging versions of standard C snprintf with extra features. -#if( DEBUG ) - DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...); + @param sbuffer Buffer to receive result. Null terminated unless the buffer size is 0. + @param buflen Size of the buffer including space for the null terminator. + @param fmt printf-style format string. + @param VAR_ARG Variable number of arguments depending on the format string. + + @result Number of characters written (minus the null terminator). + + @discussion + + Extra features over the standard C snprintf: +
+        64-bit support for %d (%lld), %i (%lli), %u (%llu), %o (%llo), %x (%llx), and %b (%llb).
+        %@   - Cocoa/CoreFoundation object. Param is the object. Strings are used directly. Others use CFCopyDescription.
+        %a   - Network Address: %.4a=IPv4, %.6a=Ethernet, %.8a Fibre Channel, %.16a=IPv6. Arg=ptr to network address.
+        %#a  - IPv4 or IPv6 mDNSAddr. Arg=ptr to mDNSAddr.
+        %##a - IPv4 (if AF_INET defined) or IPv6 (if AF_INET6 defined) sockaddr. Arg=ptr to sockaddr.
+        %b   - Binary representation of integer (e.g. 01101011). Modifiers and arg=the same as %d, %x, etc.
+        %C   - Mac-style FourCharCode (e.g. 'APPL'). Arg=32-bit value to print as a Mac-style FourCharCode.
+        %H   - Hex Dump (e.g. "\x6b\xa7" -> "6B A7"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
+        %#H  - Hex Dump & ASCII (e.g. "\x41\x62" -> "6B A7 'Ab'"). 1st arg=ptr, 2nd arg=size, 3rd arg=max size.
+        %m   - Error Message (e.g. 0 -> "kNoErr"). Modifiers and error code arg=the same as %d, %x, etc.
+        %#s  - Pascal-style length-prefixed string. Arg=ptr to string.
+        %##s - DNS label-sequence name. Arg=ptr to name.
+        %S   - UTF-16 string, 0x0000 terminated. Host order if no BOM. Precision is UTF-16 count. Precision includes BOM.
+        %#S  - Big Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
+        %##S - Little Endian UTF-16 string (unless BOM overrides). Otherwise, the same as %S.
+        %U   - Universally Unique Identifier (UUID) (e.g. 6ba7b810-9dad-11d1-80b4-00c04fd430c8). Arg=ptr to 16-byte UUID.
+    
+ */ + +#if ( DEBUG ) +DEBUG_EXPORT size_t DebugSNPrintF(char *sbuffer, size_t buflen, const char *fmt, ...); #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugSNPrintFVAList - @abstract va_list version of DebugSNPrintF. See DebugSNPrintF for more info. -*/ + @abstract va_list version of DebugSNPrintF. See DebugSNPrintF for more info. + */ -#if( DEBUG ) - DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg); +#if ( DEBUG ) +DEBUG_EXPORT size_t DebugSNPrintFVAList(char *sbuffer, size_t buflen, const char *fmt, va_list arg); #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugGetErrorString - @abstract Gets an error string from an error code. + @abstract Gets an error string from an error code. - @param inStatus Error code to get the string for. - @param inBuffer Optional buffer to copy the string to for non-static strings. May be null. - @param inBufferSize Size of optional buffer. May be 0. - - @result C string containing error string for the error code. Guaranteed to be a valid, static string. If a - buffer is supplied, the return value will always be a pointer to the supplied buffer, which will - contain the best available description of the error code. If a buffer is not supplied, the return - value will be the best available description of the error code that can be represented as a static - string. This allows code that cannot use a temporary buffer to hold the result to still get a useful - error string in most cases, but also allows code that can use a temporary buffer to get the best - available description. -*/ + @param inStatus Error code to get the string for. + @param inBuffer Optional buffer to copy the string to for non-static strings. May be null. + @param inBufferSize Size of optional buffer. May be 0. -#if( DEBUG ) - DEBUG_EXPORT const char * DebugGetErrorString( int_least32_t inErrorCode, char *inBuffer, size_t inBufferSize ); + @result C string containing error string for the error code. Guaranteed to be a valid, static string. If a + buffer is supplied, the return value will always be a pointer to the supplied buffer, which will + contain the best available description of the error code. If a buffer is not supplied, the return + value will be the best available description of the error code that can be represented as a static + string. This allows code that cannot use a temporary buffer to hold the result to still get a useful + error string in most cases, but also allows code that can use a temporary buffer to get the best + available description. + */ + +#if ( DEBUG ) +DEBUG_EXPORT const char * DebugGetErrorString( int_least32_t inErrorCode, char *inBuffer, size_t inBufferSize ); #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugHexDump - @abstract Hex dumps data to a string or to the output device. -*/ + @abstract Hex dumps data to a string or to the output device. + */ -#if( DEBUG ) - DEBUG_EXPORT size_t - DebugHexDump( - DebugLevel inLevel, - int inIndent, - const char * inLabel, - size_t inLabelSize, - int inLabelMinWidth, - const char * inType, - size_t inTypeSize, - const void * inDataStart, - const void * inData, - size_t inDataSize, - DebugFlags inFlags, - char * outBuffer, - size_t inBufferSize ); +#if ( DEBUG ) +DEBUG_EXPORT size_t +DebugHexDump( + DebugLevel inLevel, + int inIndent, + const char * inLabel, + size_t inLabelSize, + int inLabelMinWidth, + const char * inType, + size_t inTypeSize, + const void * inDataStart, + const void * inData, + size_t inDataSize, + DebugFlags inFlags, + char * outBuffer, + size_t inBufferSize ); #endif -#if( DEBUG ) - #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) \ - DebugHexDump( ( LEVEL ), (INDENT), ( LABEL ), ( LABEL_SIZE ), ( LABEL_MIN_SIZE ), ( TYPE ), ( TYPE_SIZE ), \ - ( DATA_START ), ( DATA ), ( DATA_SIZE ), ( FLAGS ), ( BUFFER ), ( BUFFER_SIZE ) ) +#if ( DEBUG ) + #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) \ + DebugHexDump( ( LEVEL ), (INDENT), ( LABEL ), ( LABEL_SIZE ), ( LABEL_MIN_SIZE ), ( TYPE ), ( TYPE_SIZE ), \ + ( DATA_START ), ( DATA ), ( DATA_SIZE ), ( FLAGS ), ( BUFFER ), ( BUFFER_SIZE ) ) #else - #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) + #define dloghex( LEVEL, INDENT, LABEL, LABEL_SIZE, LABEL_MIN_SIZE, TYPE, TYPE_SIZE, DATA_START, DATA, DATA_SIZE, FLAGS, BUFFER, BUFFER_SIZE ) #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugTaskLevel - @abstract Returns the current task level. + @abstract Returns the current task level. - @result Current task level - - @discussion - - Bit masks to isolate portions of the result (note that some masks may also need bit shifts to right justify): -
-		kDebugInterruptLevelMask				- Indicates the current interrupt level (> 0 means interrupt time).
-		kDebugInVBLTaskMask						- Indicates if a VBL task is currently being executed.
-		kDebugInDeferredTaskMask				- Indicates if a Deferred Task is currently being executed.
-		kDebugInSecondaryInterruptHandlerMask	- Indicates if a Secondary Interrupt Handler is currently being executed.
-		kDebugPageFaultFatalMask				- Indicates if it is unsafe to cause a page fault (worse than interrupt time).
-		kDebugMPTaskLevelMask					- Indicates if being called from an MP task.
-		kDebugInterruptDepthMask				- 0 means task level, 1 means in interrupt, > 1 means in nested interrupt.
-	
- - Helpers: -
-		DebugExtractTaskLevelInterruptDepth()   - Macro to extract interrupt depth from task level value.
-	
-*/ + @result Current task level -#if( DEBUG ) - DEBUG_EXPORT uint32_t DebugTaskLevel( void ); + @discussion + + Bit masks to isolate portions of the result (note that some masks may also need bit shifts to right justify): +
+        kDebugInterruptLevelMask				- Indicates the current interrupt level (> 0 means interrupt time).
+        kDebugInVBLTaskMask						- Indicates if a VBL task is currently being executed.
+        kDebugInDeferredTaskMask				- Indicates if a Deferred Task is currently being executed.
+        kDebugInSecondaryInterruptHandlerMask	- Indicates if a Secondary Interrupt Handler is currently being executed.
+        kDebugPageFaultFatalMask				- Indicates if it is unsafe to cause a page fault (worse than interrupt time).
+        kDebugMPTaskLevelMask					- Indicates if being called from an MP task.
+        kDebugInterruptDepthMask				- 0 means task level, 1 means in interrupt, > 1 means in nested interrupt.
+    
+ + Helpers: +
+        DebugExtractTaskLevelInterruptDepth()   - Macro to extract interrupt depth from task level value.
+    
+ */ + +#if ( DEBUG ) +DEBUG_EXPORT uint32_t DebugTaskLevel( void ); #endif //--------------------------------------------------------------------------------------------------------------------------- /*! @function DebugServicesTest - @abstract Unit test. -*/ + @abstract Unit test. + */ -#if( DEBUG ) - DEBUG_EXPORT OSStatus DebugServicesTest( void ); +#if ( DEBUG ) +DEBUG_EXPORT OSStatus DebugServicesTest( void ); #endif -#ifdef __cplusplus - } +#ifdef __cplusplus +} #endif -#endif // __DEBUG_SERVICES__ +#endif // __DEBUG_SERVICES__ diff --git a/bonjour-sdk/dns_sd.h b/bonjour-sdk/dns_sd.h index 3caa6a8..a1f5a57 100755 --- a/bonjour-sdk/dns_sd.h +++ b/bonjour-sdk/dns_sd.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2018 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 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 Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -54,19 +54,8 @@ * for the local network. */ - -/* _DNS_SD_H contains the mDNSResponder version number for this header file, formatted as follows: - * Major part of the build number * 10000 + - * minor part of the build number * 100 - * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as - * version 1080400. This allows C code to do simple greater-than and less-than comparisons: - * e.g. an application that requires the DNSServiceGetProperty() call (new in mDNSResponder-126) can check: - * - * #if _DNS_SD_H+0 >= 1260000 - * ... some C code that calls DNSServiceGetProperty() ... - * #endif - * - * The version defined in this header file symbol allows for compile-time +/* _DNS_SD_H contains the API version number for this header file + * The API version defined in this header file symbol allows for compile-time * checking, so that C code building with earlier versions of the header file * can avoid compile errors trying to use functions that aren't even defined * in those earlier versions. Similar checks may also be performed at run-time: @@ -77,18 +66,20 @@ */ #ifndef _DNS_SD_H -#define _DNS_SD_H 3331000 +#define _DNS_SD_H 8800035 #ifdef __cplusplus - extern "C" { +extern "C" { #endif /* Set to 1 if libdispatch is supported * Note: May also be set by project and/or Makefile */ -#ifndef _DNS_SD_LIBDISPATCH +#if defined(__APPLE__) +#define _DNS_SD_LIBDISPATCH 1 +#else #define _DNS_SD_LIBDISPATCH 0 -#endif /* ndef _DNS_SD_LIBDISPATCH */ +#endif /* standard calling convention under Win32 is __stdcall */ /* Note: When compiling Intel EFI (Extensible Firmware Interface) under MS Visual Studio, the */ @@ -99,6 +90,19 @@ #define DNSSD_API #endif +#if (defined(__GNUC__) && (__GNUC__ >= 4)) +#define DNSSD_EXPORT __attribute__((visibility("default"))) +#else +#define DNSSD_EXPORT +#endif + +#if defined(_WIN32) +#include +typedef SOCKET dnssd_sock_t; +#else +typedef int dnssd_sock_t; +#endif + /* stdint.h does not exist on FreeBSD 4.x; its types are defined in sys/types.h instead */ #if defined(__FreeBSD__) && (__FreeBSD__ < 5) #include @@ -111,24 +115,24 @@ #elif defined(EFI32) || defined(EFI64) || defined(EFIX64) #include "Tiano.h" #if !defined(_STDINT_H_) -typedef UINT8 uint8_t; -typedef INT8 int8_t; -typedef UINT16 uint16_t; -typedef INT16 int16_t; -typedef UINT32 uint32_t; -typedef INT32 int32_t; +typedef UINT8 uint8_t; +typedef INT8 int8_t; +typedef UINT16 uint16_t; +typedef INT16 int16_t; +typedef UINT32 uint32_t; +typedef INT32 int32_t; #endif /* Windows has its own differences */ #elif defined(_WIN32) #include #define _UNUSED #ifndef _MSL_STDINT_H -typedef UINT8 uint8_t; -typedef INT8 int8_t; -typedef UINT16 uint16_t; -typedef INT16 int16_t; -typedef UINT32 uint32_t; -typedef INT32 int32_t; +typedef UINT8 uint8_t; +typedef INT8 int8_t; +typedef UINT16 uint16_t; +typedef INT16 int16_t; +typedef UINT32 uint32_t; +typedef INT32 int32_t; #endif /* All other Posix platforms use stdint.h */ @@ -167,9 +171,15 @@ struct sockaddr; * The reliable way to test whether a particular bit is set is not with an equality test, * but with a bitwise mask: * if (flags & kDNSServiceFlagsAdd) ... + * With the exception of kDNSServiceFlagsValidate, each flag can be valid(be set) + * EITHER only as an input to one of the DNSService*() APIs OR only as an output + * (provide status) through any of the callbacks used. For example, kDNSServiceFlagsAdd + * can be set only as an output in the callback, whereas the kDNSServiceFlagsIncludeP2P + * can be set only as an input to the DNSService*() APIs. See comments on kDNSServiceFlagsValidate + * defined in enum below. */ enum - { +{ kDNSServiceFlagsMoreComing = 0x1, /* MoreComing indicates to a callback that at least one more result is * queued and will be delivered following immediately after this one. @@ -177,7 +187,7 @@ enum * update their UI, because this can result in a great deal of ugly flickering * on the screen, and can waste a great deal of CPU time repeatedly updating * the screen with content that is then immediately erased, over and over. - * Applications should wait until until MoreComing is not set, and then + * Applications should wait until MoreComing is not set, and then * update their UI when no more changes are imminent. * When MoreComing is not set, that doesn't mean there will be no more * answers EVER, just that there are no more answers immediately @@ -185,6 +195,15 @@ enum * in the future they will be delivered as usual. */ + kDNSServiceFlagsAutoTrigger = 0x1, + /* Valid for browses using kDNSServiceInterfaceIndexAny. + * Will auto trigger the browse over AWDL as well once the service is discoveryed + * over BLE. + * This flag is an input value to DNSServiceBrowse(), which is why we can + * use the same value as kDNSServiceFlagsMoreComing, which is an output flag + * for various client callbacks. + */ + kDNSServiceFlagsAdd = 0x2, kDNSServiceFlagsDefault = 0x4, /* Flags for domain enumeration and browse/query reply callbacks. @@ -231,14 +250,13 @@ enum * DNS, even for a name in a domain (e.g. foo.apple.com.) that would normally imply unicast DNS. */ - kDNSServiceFlagsForce = 0x800, - /* Flag for signifying a "stronger" variant of an operation. - * Currently defined only for DNSServiceReconfirmRecord(), where it forces a record to - * be removed from the cache immediately, instead of querying for a few seconds before - * concluding that the record is no longer valid and then removing it. This flag should - * be used with caution because if a service browsing PTR record is indeed still valid - * on the network, forcing its removal will result in a user-interface flap -- the - * discovered service instance will disappear, and then re-appear moments later. + kDNSServiceFlagsForce = 0x800, // This flag is deprecated. + + kDNSServiceFlagsKnownUnique = 0x800, + /* + * Client guarantees that record names are unique, so we can skip sending out initial + * probe messages. Standard name conflict resolution is still done if a conflict is discovered. + * Currently only valid for a DNSServiceRegister call. */ kDNSServiceFlagsReturnIntermediates = 0x1000, @@ -286,6 +304,7 @@ enum * ... * DNSServiceRefDeallocate(BrowseRef); // Terminate the browse operation * DNSServiceRefDeallocate(MainRef); // Terminate the shared connection + * Also see Point 4.(Don't Double-Deallocate if the MainRef has been Deallocated) in Notes below: * * Notes: * @@ -294,7 +313,7 @@ enum * kDNSServiceFlagsMoreComing flag applies collectively to *all* active * operations sharing the same parent DNSServiceRef. If the MoreComing flag is * set it means that there are more results queued on this parent DNSServiceRef, - * but not necessarily more results for this particular callback function. + * but not necessarily more results for this particular callback function. * The implication of this for client programmers is that when a callback * is invoked with the MoreComing flag set, the code should update its * internal data structures with the new result, and set a variable indicating @@ -323,7 +342,7 @@ enum * DNSServiceRef's created by other calls like DNSServiceBrowse() or DNSServiceResolve() * cannot be shared by copying them and using kDNSServiceFlagsShareConnection. * - * 4. Don't Double-Deallocate + * 4. Don't Double-Deallocate if the MainRef has been Deallocated * Calling DNSServiceRefDeallocate(ref) for a particular operation's DNSServiceRef terminates * just that operation. Calling DNSServiceRefDeallocate(ref) for the main shared DNSServiceRef * (the parent DNSServiceRef, originally created by DNSServiceCreateConnection(&ref)) @@ -335,58 +354,226 @@ enum * * 5. Thread Safety * The dns_sd.h API does not presuppose any particular threading model, and consequently - * does no locking of its own (which would require linking some specific threading library). - * If client code calls API routines on the same DNSServiceRef concurrently - * from multiple threads, it is the client's responsibility to use a mutext - * lock or take similar appropriate precautions to serialize those calls. + * does no locking internally (which would require linking with a specific threading library). + * If the client concurrently, from multiple threads (or contexts), calls API routines using + * the same DNSServiceRef, it is the client's responsibility to provide mutual exclusion for + * that DNSServiceRef. + + * For example, use of DNSServiceRefDeallocate requires caution. A common mistake is as follows: + * Thread B calls DNSServiceRefDeallocate to deallocate sdRef while Thread A is processing events + * using sdRef. Doing this will lead to intermittent crashes on thread A if the sdRef is used after + * it was deallocated. + + * A telltale sign of this crash type is to see DNSServiceProcessResult on the stack preceding the + * actual crash location. + + * To state this more explicitly, mDNSResponder does not queue DNSServiceRefDeallocate so + * that it occurs discretely before or after an event is handled. */ kDNSServiceFlagsSuppressUnusable = 0x8000, - /* - * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the - * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name) - * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses - * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly, - * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for - * "hostname". - */ + /* + * This flag is meaningful only in DNSServiceQueryRecord which suppresses unusable queries on the + * wire. If "hostname" is a wide-area unicast DNS hostname (i.e. not a ".local." name) + * but this host has no routable IPv6 address, then the call will not try to look up IPv6 addresses + * for "hostname", since any addresses it found would be unlikely to be of any use anyway. Similarly, + * if this host has no routable IPv4 address, the call will not try to look up IPv4 addresses for + * "hostname". + */ kDNSServiceFlagsTimeout = 0x10000, - /* - * When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is - * stopped after a certain number of seconds have elapsed. The time at which the query will be stopped - * is determined by the system and cannot be configured by the user. The query will be stopped irrespective - * of whether a response was given earlier or not. When the query is stopped, the callback will be called - * with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo - * and zero length rdata will be returned for DNSServiceQueryRecord. - */ + /* + * When kDNServiceFlagsTimeout is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, the query is + * stopped after a certain number of seconds have elapsed. The time at which the query will be stopped + * is determined by the system and cannot be configured by the user. The query will be stopped irrespective + * of whether a response was given earlier or not. When the query is stopped, the callback will be called + * with an error code of kDNSServiceErr_Timeout and a NULL sockaddr will be returned for DNSServiceGetAddrInfo + * and zero length rdata will be returned for DNSServiceQueryRecord. + */ kDNSServiceFlagsIncludeP2P = 0x20000, - /* - * Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified. - * By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces. - */ - kDNSServiceFlagsWakeOnResolve = 0x40000 - /* - * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet - * to wake up the client. - */ - }; + /* + * Include P2P interfaces when kDNSServiceInterfaceIndexAny is specified. + * By default, specifying kDNSServiceInterfaceIndexAny does not include P2P interfaces. + */ -/* Possible protocols for DNSServiceNATPortMappingCreate(). */ + kDNSServiceFlagsWakeOnResolve = 0x40000, + /* + * This flag is meaningful only in DNSServiceResolve. When set, it tries to send a magic packet + * to wake up the client. + */ + + kDNSServiceFlagsBackgroundTrafficClass = 0x80000, + /* + * This flag is meaningful for Unicast DNS queries. When set, it uses the background traffic + * class for packets that service the request. + */ + + kDNSServiceFlagsIncludeAWDL = 0x100000, + /* + * Include AWDL interface when kDNSServiceInterfaceIndexAny is specified. + */ + + kDNSServiceFlagsValidate = 0x200000, + /* + * This flag is meaningful in DNSServiceGetAddrInfo and DNSServiceQueryRecord. This is the ONLY flag to be valid + * as an input to the APIs and also an output through the callbacks in the APIs. + * + * When this flag is passed to DNSServiceQueryRecord and DNSServiceGetAddrInfo to resolve unicast names, + * the response will be validated using DNSSEC. The validation results are delivered using the flags field in + * the callback and kDNSServiceFlagsValidate is marked in the flags to indicate that DNSSEC status is also available. + * When the callback is called to deliver the query results, the validation results may or may not be available. + * If it is not delivered along with the results, the validation status is delivered when the validation completes. + * + * When the validation results are delivered in the callback, it is indicated by marking the flags with + * kDNSServiceFlagsValidate and kDNSServiceFlagsAdd along with the DNSSEC status flags (described below) and a NULL + * sockaddr will be returned for DNSServiceGetAddrInfo and zero length rdata will be returned for DNSServiceQueryRecord. + * DNSSEC validation results are for the whole RRSet and not just individual records delivered in the callback. When + * kDNSServiceFlagsAdd is not set in the flags, applications should implicitly assume that the DNSSEC status of the + * RRSet that has been delivered up until that point is not valid anymore, till another callback is called with + * kDNSServiceFlagsAdd and kDNSServiceFlagsValidate. + * + * The following four flags indicate the status of the DNSSEC validation and marked in the flags field of the callback. + * When any of the four flags is set, kDNSServiceFlagsValidate will also be set. To check the validation status, the + * other applicable output flags should be masked. See kDNSServiceOutputFlags below. + */ + + kDNSServiceFlagsSecure = 0x200010, + /* + * The response has been validated by verifying all the signatures in the response and was able to + * build a successful authentication chain starting from a known trust anchor. + */ + + kDNSServiceFlagsInsecure = 0x200020, + /* + * A chain of trust cannot be built starting from a known trust anchor to the response. + */ + + kDNSServiceFlagsBogus = 0x200040, + /* + * If the response cannot be verified to be secure due to expired signatures, missing signatures etc., + * then the results are considered to be bogus. + */ + + kDNSServiceFlagsIndeterminate = 0x200080, + /* + * There is no valid trust anchor that can be used to determine whether a response is secure or not. + */ + + kDNSServiceFlagsUnicastResponse = 0x400000, + /* + * Request unicast response to query. + */ + kDNSServiceFlagsValidateOptional = 0x800000, + + /* + * This flag is identical to kDNSServiceFlagsValidate except for the case where the response + * cannot be validated. If this flag is set in DNSServiceQueryRecord or DNSServiceGetAddrInfo, + * the DNSSEC records will be requested for validation. If they cannot be received for some reason + * during the validation (e.g., zone is not signed, zone is signed but cannot be traced back to + * root, recursive server does not understand DNSSEC etc.), then this will fallback to the default + * behavior where the validation will not be performed and no DNSSEC results will be provided. + * + * If the zone is signed and there is a valid path to a known trust anchor configured in the system + * and the application requires DNSSEC validation irrespective of the DNSSEC awareness in the current + * network, then this option MUST not be used. This is only intended to be used during the transition + * period where the different nodes participating in the DNS resolution may not understand DNSSEC or + * managed properly (e.g. missing DS record) but still want to be able to resolve DNS successfully. + */ + + kDNSServiceFlagsWakeOnlyService = 0x1000000, + /* + * This flag is meaningful only in DNSServiceRegister. When set, the service will not be registered + * with sleep proxy server during sleep. + */ + + kDNSServiceFlagsThresholdOne = 0x2000000, + kDNSServiceFlagsThresholdFinder = 0x4000000, + kDNSServiceFlagsThresholdReached = kDNSServiceFlagsThresholdOne, + /* + * kDNSServiceFlagsThresholdOne is meaningful only in DNSServiceBrowse. When set, + * the system will stop issuing browse queries on the network once the number + * of answers returned is one or more. It will issue queries on the network + * again if the number of answers drops to zero. + * This flag is for Apple internal use only. Third party developers + * should not rely on this behavior being supported in any given software release. + * + * kDNSServiceFlagsThresholdFinder is meaningful only in DNSServiceBrowse. When set, + * the system will stop issuing browse queries on the network once the number + * of answers has reached the threshold set for Finder. + * It will issue queries on the network again if the number of answers drops below + * this threshold. + * This flag is for Apple internal use only. Third party developers + * should not rely on this behavior being supported in any given software release. + * + * When kDNSServiceFlagsThresholdReached is set in the client callback add or remove event, + * it indicates that the browse answer threshold has been reached and no + * browse requests will be generated on the network until the number of answers falls + * below the threshold value. Add and remove events can still occur based + * on incoming Bonjour traffic observed by the system. + * The set of services return to the client is not guaranteed to represent the + * entire set of services present on the network once the threshold has been reached. + * + * Note, while kDNSServiceFlagsThresholdReached and kDNSServiceFlagsThresholdOne + * have the same value, there isn't a conflict because kDNSServiceFlagsThresholdReached + * is only set in the callbacks and kDNSServiceFlagsThresholdOne is only set on + * input to a DNSServiceBrowse call. + */ + kDNSServiceFlagsPrivateOne = 0x8000000, + /* + * This flag is private and should not be used. + */ + + kDNSServiceFlagsPrivateTwo = 0x10000000, + /* + * This flag is private and should not be used. + */ + + kDNSServiceFlagsPrivateThree = 0x20000000, + /* + * This flag is private and should not be used. + */ + + kDNSServiceFlagsPrivateFour = 0x40000000, + /* + * This flag is private and should not be used. + */ + + kDNSServiceFlagsAllowExpiredAnswers = 0x80000000, + /* + * When kDNSServiceFlagsAllowExpiredAnswers is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, + * if there are matching expired records still in the cache, then they are immediately returned to the + * client, and in parallel a network query for that name is issued. All returned records from the query will + * remain in the cache after expiration. + */ + + kDNSServiceFlagsExpiredAnswer = 0x80000000 + /* + * When kDNSServiceFlagsAllowExpiredAnswers is passed to DNSServiceQueryRecord or DNSServiceGetAddrInfo, + * an expired answer will have this flag set. + */ + +}; + +#define kDNSServiceOutputFlags (kDNSServiceFlagsValidate | kDNSServiceFlagsValidateOptional | kDNSServiceFlagsMoreComing | kDNSServiceFlagsAdd | kDNSServiceFlagsDefault) + /* All the output flags excluding the DNSSEC Status flags. Typically used to check DNSSEC Status */ + +/* Possible protocol values */ enum - { +{ + /* for DNSServiceGetAddrInfo() */ kDNSServiceProtocol_IPv4 = 0x01, kDNSServiceProtocol_IPv6 = 0x02, /* 0x04 and 0x08 reserved for future internetwork protocols */ - + + /* for DNSServiceNATPortMappingCreate() */ kDNSServiceProtocol_UDP = 0x10, kDNSServiceProtocol_TCP = 0x20 - /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960] - * or DCCP [RFC 4340]. If future NAT gateways are created that support port - * mappings for these protocols, new constants will be defined here. - */ - }; + /* 0x40 and 0x80 reserved for future transport protocols, e.g. SCTP [RFC 2960] + * or DCCP [RFC 4340]. If future NAT gateways are created that support port + * mappings for these protocols, new constants will be defined here. + */ +}; /* * The values for DNS Classes and Types are listed in RFC 1035, and are available @@ -400,12 +587,12 @@ enum */ enum - { +{ kDNSServiceClass_IN = 1 /* Internet */ - }; +}; enum - { +{ kDNSServiceType_A = 1, /* Host address. */ kDNSServiceType_NS = 2, /* Authoritative server. */ kDNSServiceType_MD = 3, /* Mail destination. */ @@ -473,11 +660,11 @@ enum kDNSServiceType_MAILB = 253, /* Transfer mailbox records. */ kDNSServiceType_MAILA = 254, /* Transfer mail agent records. */ kDNSServiceType_ANY = 255 /* Wildcard match. */ - }; +}; /* possible error code values */ enum - { +{ kDNSServiceErr_NoError = 0, kDNSServiceErr_Unknown = -65537, /* 0xFFFE FFFF */ kDNSServiceErr_NoSuchName = -65538, @@ -505,15 +692,15 @@ enum kDNSServiceErr_BadKey = -65561, kDNSServiceErr_Transient = -65562, kDNSServiceErr_ServiceNotRunning = -65563, /* Background daemon not running */ - kDNSServiceErr_NATPortMappingUnsupported = -65564, /* NAT doesn't support NAT-PMP or UPnP */ - kDNSServiceErr_NATPortMappingDisabled = -65565, /* NAT supports NAT-PMP or UPnP but it's disabled by the administrator */ + kDNSServiceErr_NATPortMappingUnsupported = -65564, /* NAT doesn't support PCP, NAT-PMP or UPnP */ + kDNSServiceErr_NATPortMappingDisabled = -65565, /* NAT supports PCP, NAT-PMP or UPnP, but it's disabled by the administrator */ kDNSServiceErr_NoRouter = -65566, /* No router currently configured (probably no network connectivity) */ kDNSServiceErr_PollingMode = -65567, kDNSServiceErr_Timeout = -65568 - /* mDNS Error codes are in the range - * FFFE FF00 (-65792) to FFFE FFFF (-65537) */ - }; + /* mDNS Error codes are in the range + * FFFE FF00 (-65792) to FFFE FFFF (-65537) */ +}; /* Maximum length, in bytes, of a service name represented as a */ /* literal C-String, including the terminating NULL at the end. */ @@ -530,24 +717,49 @@ enum * -- or -- * "Why is kDNSServiceMaxDomainName 1009, when the maximum legal domain name is 256 bytes?" * - * All strings used in the DNS-SD APIs are UTF-8 strings. Apart from the exceptions noted below, - * the APIs expect the strings to be properly escaped, using the conventional DNS escaping rules: + * All strings used in the DNS-SD APIs are UTF-8 strings. + * Apart from the exceptions noted below, the APIs expect the strings to be properly escaped, using the + * conventional DNS escaping rules, as used by the traditional DNS res_query() API, as described below: * - * '\\' represents a single literal '\' in the name - * '\.' represents a single literal '.' in the name + * Generally all UTF-8 characters (which includes all US ASCII characters) represent themselves, + * with two exceptions, the dot ('.') character, which is the label separator, + * and the backslash ('\') character, which is the escape character. + * The escape character ('\') is interpreted as described below: + * * '\ddd', where ddd is a three-digit decimal value from 000 to 255, - * represents a single literal byte with that value. - * A bare unescaped '.' is a label separator, marking a boundary between domain and subdomain. + * represents a single literal byte with that value. Any byte value may be + * represented in '\ddd' format, even characters that don't strictly need to be escaped. + * For example, the ASCII code for 'w' is 119, and therefore '\119' is equivalent to 'w'. + * Thus the command "ping '\119\119\119.apple.com'" is the equivalent to the command "ping 'www.apple.com'". + * Nonprinting ASCII characters in the range 0-31 are often represented this way. + * In particular, the ASCII NUL character (0) cannot appear in a C string because C uses it as the + * string terminator character, so ASCII NUL in a domain name has to be represented in a C string as '\000'. + * Other characters like space (ASCII code 32) are sometimes represented as '\032' + * in contexts where having an actual space character in a C string would be inconvenient. + * + * Otherwise, for all cases where a '\' is followed by anything other than a three-digit decimal value + * from 000 to 255, the character sequence '\x' represents a single literal occurrence of character 'x'. + * This is legal for any character, so, for example, '\w' is equivalent to 'w'. + * Thus the command "ping '\w\w\w.apple.com'" is the equivalent to the command "ping 'www.apple.com'". + * However, this encoding is most useful when representing the characters '.' and '\', + * which otherwise would have special meaning in DNS name strings. + * This means that the following encodings are particularly common: + * '\\' represents a single literal '\' in the name + * '\.' represents a single literal '.' in the name + * + * A lone escape character ('\') appearing at the end of a string is not allowed, since it is + * followed by neither a three-digit decimal value from 000 to 255 nor a single character. + * If a lone escape character ('\') does appear as the last character of a string, it is silently ignored. * * The exceptions, that do not use escaping, are the routines where the full * DNS name of a resource is broken, for convenience, into servicename/regtype/domain. * In these routines, the "servicename" is NOT escaped. It does not need to be, since * it is, by definition, just a single literal string. Any characters in that string * represent exactly what they are. The "regtype" portion is, technically speaking, - * escaped, but since legal regtypes are only allowed to contain letters, digits, - * and hyphens, there is nothing to escape, so the issue is moot. The "domain" - * portion is also escaped, though most domains in use on the public Internet - * today, like regtypes, don't contain any characters that need to be escaped. + * escaped, but since legal regtypes are only allowed to contain US ASCII letters, + * digits, and hyphens, there is nothing to escape, so the issue is moot. + * The "domain" portion is also escaped, though most domains in use on the public + * Internet today, like regtypes, don't contain any characters that need to be escaped. * As DNS-SD becomes more popular, rich-text domains for service discovery will * become common, so software should be written to cope with domains with escaping. * @@ -567,7 +779,7 @@ enum * full DNS name, the helper function DNSServiceConstructFullName() is provided. * * The following (highly contrived) example illustrates the escaping process. - * Suppose you have an service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp" + * Suppose you have a service called "Dr. Smith\Dr. Johnson", of type "_ftp._tcp" * in subdomain "4th. Floor" of subdomain "Building 2" of domain "apple.com." * The full (escaped) DNS name of this service's SRV record would be: * Dr\.\032Smith\\Dr\.\032Johnson._ftp._tcp.4th\.\032Floor.Building\0322.apple.com. @@ -587,9 +799,8 @@ enum * DNS server." Normally, most clients will use 0 for interface index to * automatically get the default sensible behaviour. * - * If the client passes a positive interface index, then for multicast names that - * indicates to do the operation only on that one interface. For unicast names the - * interface index is ignored unless kDNSServiceFlagsForceMulticast is also set. + * If the client passes a positive interface index, then that indicates to do the + * operation only on that one specified interface. * * If the client passes kDNSServiceInterfaceIndexLocalOnly when registering * a service, then that service will be found *only* by other local clients @@ -600,29 +811,50 @@ enum * in a way such that it does not inadvertently appear in service lists on * all the other machines on the network. * - * If the client passes kDNSServiceInterfaceIndexLocalOnly when browsing - * then it will find *all* records registered on that same local machine. - * Clients explicitly wishing to discover *only* LocalOnly services can - * accomplish this by inspecting the interfaceIndex of each service reported - * to their DNSServiceBrowseReply() callback function, and discarding those - * where the interface index is not kDNSServiceInterfaceIndexLocalOnly. + * If the client passes kDNSServiceInterfaceIndexLocalOnly when querying or + * browsing, then the LocalOnly authoritative records and /etc/hosts caches + * are searched and will find *all* records registered or configured on that + * same local machine. * - * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, + * If interested in getting negative answers to local questions while querying + * or browsing, then set both the kDNSServiceInterfaceIndexLocalOnly and the + * kDNSServiceFlagsReturnIntermediates flags. If no local answers exist at this + * moment in time, then the reply will return an immediate negative answer. If + * local records are subsequently created that answer the question, then those + * answers will be delivered, for as long as the question is still active. + * + * If the kDNSServiceFlagsTimeout and kDNSServiceInterfaceIndexLocalOnly flags + * are set simultaneously when either DNSServiceQueryRecord or DNSServiceGetAddrInfo + * is called then both flags take effect. However, if DNSServiceQueryRecord is called + * with both the kDNSServiceFlagsSuppressUnusable and kDNSServiceInterfaceIndexLocalOnly + * flags set, then the kDNSServiceFlagsSuppressUnusable flag is ignored. + * + * Clients explicitly wishing to discover *only* LocalOnly services during a + * browse may do this, without flags, by inspecting the interfaceIndex of each + * service reported to a DNSServiceBrowseReply() callback function, and + * discarding those answers where the interface index is not set to + * kDNSServiceInterfaceIndexLocalOnly. + * + * kDNSServiceInterfaceIndexP2P is meaningful only in Browse, QueryRecord, Register, * and Resolve operations. It should not be used in other DNSService APIs. * * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceBrowse or * DNSServiceQueryRecord, it restricts the operation to P2P. * + * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceRegister, it is + * mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P + * set. + * * - If kDNSServiceInterfaceIndexP2P is passed to DNSServiceResolve, it is - * mapped internally to kDNSServiceInterfaceIndexAny, because resolving - * a P2P service may create and/or enable an interface whose index is not - * known a priori. The resolve callback will indicate the index of the + * mapped internally to kDNSServiceInterfaceIndexAny with the kDNSServiceFlagsIncludeP2P + * set, because resolving a P2P service may create and/or enable an interface whose + * index is not known a priori. The resolve callback will indicate the index of the * interface via which the service can be accessed. * * If applications pass kDNSServiceInterfaceIndexAny to DNSServiceBrowse * or DNSServiceQueryRecord, they must set the kDNSServiceFlagsIncludeP2P flag - * to include P2P. In this case, if a service instance or the record being queried - * is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P + * to include P2P. In this case, if a service instance or the record being queried + * is found over P2P, the resulting ADD event will indicate kDNSServiceInterfaceIndexP2P * as the interface index. */ @@ -630,17 +862,18 @@ enum #define kDNSServiceInterfaceIndexLocalOnly ((uint32_t)-1) #define kDNSServiceInterfaceIndexUnicast ((uint32_t)-2) #define kDNSServiceInterfaceIndexP2P ((uint32_t)-3) +#define kDNSServiceInterfaceIndexBLE ((uint32_t)-4) typedef uint32_t DNSServiceFlags; typedef uint32_t DNSServiceProtocol; -typedef int32_t DNSServiceErrorType; +typedef int32_t DNSServiceErrorType; /********************************************************************************************* - * - * Version checking - * - *********************************************************************************************/ +* +* Version checking +* +*********************************************************************************************/ /* DNSServiceGetProperty() Parameters: * @@ -660,49 +893,45 @@ typedef int32_t DNSServiceErrorType; * if the daemon (or "system service" on Windows) is not running. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceGetProperty - ( +( const char *property, /* Requested property (i.e. kDNSServiceProperty_DaemonVersion) */ void *result, /* Pointer to place to store result */ uint32_t *size /* size of result location */ - ); +); /* * When requesting kDNSServiceProperty_DaemonVersion, the result pointer must point * to a 32-bit unsigned integer, and the size parameter must be set to sizeof(uint32_t). * - * On return, the 32-bit unsigned integer contains the version number, formatted as follows: - * Major part of the build number * 10000 + - * minor part of the build number * 100 - * - * For example, Mac OS X 10.4.9 has mDNSResponder-108.4, which would be represented as - * version 1080400. This allows applications to do simple greater-than and less-than comparisons: - * e.g. an application that requires at least mDNSResponder-108.4 can check: + * On return, the 32-bit unsigned integer contains the API version number * + * For example, Mac OS X 10.4.9 has API version 1080400. + * This allows applications to do simple greater-than and less-than comparisons: + * e.g. an application that requires at least API version 1080400 can check: * if (version >= 1080400) ... * * Example usage: - * * uint32_t version; * uint32_t size = sizeof(version); * DNSServiceErrorType err = DNSServiceGetProperty(kDNSServiceProperty_DaemonVersion, &version, &size); - * if (!err) printf("Bonjour version is %d.%d\n", version / 10000, version / 100 % 100); + * if (!err) printf("DNS_SD API version is %d.%d\n", version / 10000, version / 100 % 100); */ #define kDNSServiceProperty_DaemonVersion "DaemonVersion" - /********************************************************************************************* - * - * Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions - * - *********************************************************************************************/ +* +* Unix Domain Socket access, DNSServiceRef deallocation, and data processing functions +* +*********************************************************************************************/ /* DNSServiceRefSockFD() * * Access underlying Unix domain socket for an initialized DNSServiceRef. * The DNS Service Discovery implementation uses this socket to communicate between the client and - * the mDNSResponder daemon. The application MUST NOT directly read from or write to this socket. + * the daemon. The application MUST NOT directly read from or write to this socket. * Access to the socket is provided so that it can be used as a kqueue event source, a CFRunLoop * event source, in a select() loop, etc. When the underlying event management subsystem (kqueue/ * select/CFRunLoop etc.) indicates to the client that data is available for reading on the @@ -712,6 +941,8 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty * a client can choose to fork a thread and have it loop calling "DNSServiceProcessResult(ref);" * If DNSServiceProcessResult() is called when no data is available for reading on the socket, it * will block until data does become available, and then process the data and return to the caller. + * The application is responsible for checking the return value of DNSServiceProcessResult() + * to determine if the socket is valid and if it should continue to process data on the socket. * When data arrives on the socket, the client is responsible for calling DNSServiceProcessResult(ref) * in a timely fashion -- if the client allows a large backlog of data to build up the daemon * may terminate the connection. @@ -722,7 +953,8 @@ DNSServiceErrorType DNSSD_API DNSServiceGetProperty * error. */ -int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); +DNSSD_EXPORT +dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); /* DNSServiceProcessResult() @@ -743,6 +975,7 @@ int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef); * an error code indicating the specific failure that occurred. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef); @@ -764,22 +997,21 @@ DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef); * is invalidated when this function is called - the DNSRecordRef may not be used in subsequent * functions. * - * Note: This call is to be used only with the DNSServiceRef defined by this API. It is - * not compatible with dns_service_discovery_ref objects defined in the legacy Mach-based - * DNSServiceDiscovery.h API. + * Note: This call is to be used only with the DNSServiceRef defined by this API. * * sdRef: A DNSServiceRef initialized by any of the DNSService calls. * */ +DNSSD_EXPORT void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef); /********************************************************************************************* - * - * Domain Enumeration - * - *********************************************************************************************/ +* +* Domain Enumeration +* +*********************************************************************************************/ /* DNSServiceEnumerateDomains() * @@ -817,14 +1049,14 @@ void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef); */ typedef void (DNSSD_API *DNSServiceDomainEnumReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *replyDomain, void *context - ); +); /* DNSServiceEnumerateDomains() Parameters: @@ -856,21 +1088,22 @@ typedef void (DNSSD_API *DNSServiceDomainEnumReply) * is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceDomainEnumReply callBack, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceDomainEnumReply callBack, void *context /* may be NULL */ - ); +); /********************************************************************************************* - * - * Service Registration - * - *********************************************************************************************/ +* +* Service Registration +* +*********************************************************************************************/ /* Register a service that is discovered via Browse() and Resolve() calls. * @@ -908,15 +1141,15 @@ DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains */ typedef void (DNSSD_API *DNSServiceRegisterReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + DNSServiceErrorType errorCode, const char *name, const char *regtype, const char *domain, void *context - ); +); /* DNSServiceRegister() Parameters: @@ -926,14 +1159,14 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * and the registration will remain active indefinitely until the client * terminates it by passing this DNSServiceRef to DNSServiceRefDeallocate(). * + * flags: Indicates the renaming behavior on name conflict (most applications + * will pass 0). See flag definitions above for details. + * * interfaceIndex: If non-zero, specifies the interface on which to register the service * (the index for a given interface is determined via the if_nametoindex() * family of calls.) Most applications will pass 0 to register on all * available interfaces. See "Constants for specifying an interface index" for more details. * - * flags: Indicates the renaming behavior on name conflict (most applications - * will pass 0). See flag definitions above for details. - * * name: If non-NULL, specifies the service name to be registered. * Most applications will not specify a name, in which case the computer * name is used (this name is communicated to the client via the callback). @@ -974,9 +1207,34 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * bit byte values, including zero bytes. However, due to the nature of * using a C-string-based API, conventional DNS escaping must be used for * dots ('.'), commas (','), backslashes ('\') and zero bytes, as shown below: - * + * * % dns-sd -R Test '_test._tcp,s\.one,s\,two,s\\three,s\000four' local 123 * + * When a service is registered, all the clients browsing for the registered + * type ("regtype") will discover it. If the discovery should be + * restricted to a smaller set of well known peers, the service can be + * registered with additional data (group identifier) that is known + * only to a smaller set of peers. The group identifier should follow primary + * service type using a colon (":") as a delimeter. If subtypes are also present, + * it should be given before the subtype as shown below. + * + * % dns-sd -R _test1 _http._tcp:mygroup1 local 1001 + * % dns-sd -R _test2 _http._tcp:mygroup2 local 1001 + * % dns-sd -R _test3 _http._tcp:mygroup3,HasFeatureA local 1001 + * + * Now: + * % dns-sd -B _http._tcp:"mygroup1" # will discover only test1 + * % dns-sd -B _http._tcp:"mygroup2" # will discover only test2 + * % dns-sd -B _http._tcp:"mygroup3",HasFeatureA # will discover only test3 + * + * By specifying the group information, only the members of that group are + * discovered. + * + * The group identifier itself is not sent in clear. Only a hash of the group + * identifier is sent and the clients discover them anonymously. The group identifier + * may be up to 256 bytes long and may contain any eight bit values except comma which + * should be escaped. + * * domain: If non-NULL, specifies the domain on which to advertise the service. * Most applications will not specify a domain, instead automatically * registering in the default domain(s). @@ -1021,21 +1279,22 @@ typedef void (DNSSD_API *DNSServiceRegisterReply) * is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceRegister - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *name, /* may be NULL */ const char *regtype, const char *domain, /* may be NULL */ const char *host, /* may be NULL */ - uint16_t port, /* In network byte order */ - uint16_t txtLen, + uint16_t port, /* In network byte order */ + uint16_t txtLen, const void *txtRecord, /* may be NULL */ - DNSServiceRegisterReply callBack, /* may be NULL */ + DNSServiceRegisterReply callBack, /* may be NULL */ void *context /* may be NULL */ - ); +); /* DNSServiceAddRecord() @@ -1048,7 +1307,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister * Note that the DNSServiceAddRecord/UpdateRecord/RemoveRecord are *NOT* thread-safe * with respect to a single DNSServiceRef. If you plan to have multiple threads * in your program simultaneously add, update, or remove records from the same - * DNSServiceRef, then it's the caller's responsibility to use a mutext lock + * DNSServiceRef, then it's the caller's responsibility to use a mutex lock * or take similar appropriate precautions to serialize those calls. * * Parameters; @@ -1076,16 +1335,17 @@ DNSServiceErrorType DNSSD_API DNSServiceRegister * error code indicating the error that occurred (the RecordRef is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceAddRecord - ( - DNSServiceRef sdRef, +( + DNSServiceRef sdRef, DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint16_t rrtype, - uint16_t rdlen, + DNSServiceFlags flags, + uint16_t rrtype, + uint16_t rdlen, const void *rdata, - uint32_t ttl - ); + uint32_t ttl +); /* DNSServiceUpdateRecord @@ -1117,21 +1377,22 @@ DNSServiceErrorType DNSSD_API DNSServiceAddRecord * error code indicating the error that occurred. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, /* may be NULL */ - DNSServiceFlags flags, - uint16_t rdlen, +( + DNSServiceRef sdRef, + DNSRecordRef RecordRef, /* may be NULL */ + DNSServiceFlags flags, + uint16_t rdlen, const void *rdata, - uint32_t ttl - ); + uint32_t ttl +); /* DNSServiceRemoveRecord * * Remove a record previously added to a service record set via DNSServiceAddRecord(), or deregister - * an record registered individually via DNSServiceRegisterRecord(). + * a record registered individually via DNSServiceRegisterRecord(). * * Parameters: * @@ -1149,19 +1410,20 @@ DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord * error code indicating the error that occurred. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags - ); +( + DNSServiceRef sdRef, + DNSRecordRef RecordRef, + DNSServiceFlags flags +); /********************************************************************************************* - * - * Service Discovery - * - *********************************************************************************************/ +* +* Service Discovery +* +*********************************************************************************************/ /* Browse for instances of a service. * @@ -1202,16 +1464,16 @@ DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord */ typedef void (DNSSD_API *DNSServiceBrowseReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *serviceName, const char *regtype, const char *replyDomain, void *context - ); +); /* DNSServiceBrowse() Parameters: @@ -1233,7 +1495,10 @@ typedef void (DNSSD_API *DNSServiceBrowseReply) * A client may optionally specify a single subtype to perform filtered browsing: * e.g. browsing for "_primarytype._tcp,_subtype" will discover only those * instances of "_primarytype._tcp" that were registered specifying "_subtype" - * in their list of registered subtypes. + * in their list of registered subtypes. Additionally, a group identifier may + * also be specified before the subtype e.g., _primarytype._tcp:GroupID, which + * will discover only the members that register the service with GroupID. See + * DNSServiceRegister for more details. * * domain: If non-NULL, specifies the domain on which to browse for services. * Most applications will not specify a domain, instead browsing on the @@ -1251,16 +1516,17 @@ typedef void (DNSSD_API *DNSServiceBrowseReply) * is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceBrowse - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *regtype, const char *domain, /* may be NULL */ - DNSServiceBrowseReply callBack, + DNSServiceBrowseReply callBack, void *context /* may be NULL */ - ); +); /* DNSServiceResolve() @@ -1325,18 +1591,18 @@ DNSServiceErrorType DNSSD_API DNSServiceBrowse */ typedef void (DNSSD_API *DNSServiceResolveReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *fullname, const char *hosttarget, - uint16_t port, /* In network byte order */ - uint16_t txtLen, + uint16_t port, /* In network byte order */ + uint16_t txtLen, const unsigned char *txtRecord, void *context - ); +); /* DNSServiceResolve() Parameters @@ -1379,24 +1645,25 @@ typedef void (DNSSD_API *DNSServiceResolveReply) * is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceResolve - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *name, const char *regtype, const char *domain, - DNSServiceResolveReply callBack, + DNSServiceResolveReply callBack, void *context /* may be NULL */ - ); +); /********************************************************************************************* - * - * Querying Individual Specific Records - * - *********************************************************************************************/ +* +* Querying Individual Specific Records +* +*********************************************************************************************/ /* DNSServiceQueryRecord * @@ -1436,26 +1703,28 @@ DNSServiceErrorType DNSSD_API DNSServiceResolve * only applies to clients that cancel the asynchronous operation when * they get a result. Clients that leave the asynchronous operation * running can safely assume that the data remains valid until they - * get another callback telling them otherwise. + * get another callback telling them otherwise. The ttl value is not + * updated when the daemon answers from the cache, hence relying on + * the accuracy of the ttl value is not recommended. * * context: The context pointer that was passed to the callout. * */ typedef void (DNSSD_API *DNSServiceQueryRecordReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata, - uint32_t ttl, + uint32_t ttl, void *context - ); +); /* DNSServiceQueryRecord() Parameters: @@ -1467,11 +1736,8 @@ typedef void (DNSSD_API *DNSServiceQueryRecordReply) * * flags: kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery. * Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast - * query in a non-local domain. Without setting this flag, unicast queries - * will be one-shot - that is, only answers available at the time of the call - * will be returned. By setting this flag, answers (including Add and Remove - * events) that become available after the initial call is made will generate - * callbacks. This flag has no effect on link-local multicast queries. + * query to a unicast DNS server that implements the protocol. This flag + * has no effect on link-local multicast queries. * * interfaceIndex: If non-zero, specifies the interface on which to issue the query * (the index for a given interface is determined via the if_nametoindex() @@ -1497,24 +1763,25 @@ typedef void (DNSSD_API *DNSServiceQueryRecordReply) * is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceQueryRecord - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - DNSServiceQueryRecordReply callBack, + uint16_t rrtype, + uint16_t rrclass, + DNSServiceQueryRecordReply callBack, void *context /* may be NULL */ - ); +); /********************************************************************************************* - * - * Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname - * - *********************************************************************************************/ +* +* Unified lookup of both IPv4 and IPv6 addresses for a fully qualified hostname +* +*********************************************************************************************/ /* DNSServiceGetAddrInfo * @@ -1545,23 +1812,25 @@ DNSServiceErrorType DNSSD_API DNSServiceQueryRecord * only applies to clients that cancel the asynchronous operation when * they get a result. Clients that leave the asynchronous operation * running can safely assume that the data remains valid until they - * get another callback telling them otherwise. + * get another callback telling them otherwise. The ttl value is not + * updated when the daemon answers from the cache, hence relying on + * the accuracy of the ttl value is not recommended. * * context: The context pointer that was passed to the callout. * */ typedef void (DNSSD_API *DNSServiceGetAddrInfoReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, const char *hostname, const struct sockaddr *address, - uint32_t ttl, + uint32_t ttl, void *context - ); +); /* DNSServiceGetAddrInfo() Parameters: @@ -1571,13 +1840,7 @@ typedef void (DNSSD_API *DNSServiceGetAddrInfoReply) * begins and will last indefinitely until the client terminates the query * by passing this DNSServiceRef to DNSServiceRefDeallocate(). * - * flags: kDNSServiceFlagsForceMulticast or kDNSServiceFlagsLongLivedQuery. - * Pass kDNSServiceFlagsLongLivedQuery to create a "long-lived" unicast - * query in a non-local domain. Without setting this flag, unicast queries - * will be one-shot - that is, only answers available at the time of the call - * will be returned. By setting this flag, answers (including Add and Remove - * events) that become available after the initial call is made will generate - * callbacks. This flag has no effect on link-local multicast queries. + * flags: kDNSServiceFlagsForceMulticast * * interfaceIndex: The interface on which to issue the query. Passing 0 causes the query to be * sent on all active interfaces via Multicast or the primary interface via Unicast. @@ -1605,25 +1868,26 @@ typedef void (DNSSD_API *DNSServiceGetAddrInfoReply) * the error that occurred. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceProtocol protocol, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceProtocol protocol, const char *hostname, - DNSServiceGetAddrInfoReply callBack, + DNSServiceGetAddrInfoReply callBack, void *context /* may be NULL */ - ); +); /********************************************************************************************* - * - * Special Purpose Calls: - * DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord() - * (most applications will not use these) - * - *********************************************************************************************/ +* +* Special Purpose Calls: +* DNSServiceCreateConnection(), DNSServiceRegisterRecord(), DNSServiceReconfirmRecord() +* (most applications will not use these) +* +*********************************************************************************************/ /* DNSServiceCreateConnection() * @@ -1641,9 +1905,9 @@ DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo * case the DNSServiceRef is not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); - /* DNSServiceRegisterRecord * * Register an individual resource record on a connected DNSServiceRef. @@ -1670,14 +1934,14 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); * */ - typedef void (DNSSD_API *DNSServiceRegisterRecordReply) - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags, - DNSServiceErrorType errorCode, +typedef void (DNSSD_API *DNSServiceRegisterRecordReply) +( + DNSServiceRef sdRef, + DNSRecordRef RecordRef, + DNSServiceFlags flags, + DNSServiceErrorType errorCode, void *context - ); +); /* DNSServiceRegisterRecord() Parameters: @@ -1724,21 +1988,22 @@ DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef); * not initialized). */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord - ( - DNSServiceRef sdRef, +( + DNSServiceRef sdRef, DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata, - uint32_t ttl, - DNSServiceRegisterRecordReply callBack, + uint32_t ttl, + DNSServiceRegisterRecordReply callBack, void *context /* may be NULL */ - ); +); /* DNSServiceReconfirmRecord @@ -1752,8 +2017,7 @@ DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord * * Parameters: * - * flags: Pass kDNSServiceFlagsForce to force immediate deletion of record, - * instead of after some number of reconfirmation queries have gone unanswered. + * flags: Not currently used. * * interfaceIndex: Specifies the interface of the record in question. * The caller must specify the interface. @@ -1774,29 +2038,34 @@ DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord * */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord - ( - DNSServiceFlags flags, - uint32_t interfaceIndex, +( + DNSServiceFlags flags, + uint32_t interfaceIndex, const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, const void *rdata - ); +); /********************************************************************************************* - * - * NAT Port Mapping - * - *********************************************************************************************/ +* +* NAT Port Mapping +* +*********************************************************************************************/ /* DNSServiceNATPortMappingCreate * * Request a port mapping in the NAT gateway, which maps a port on the local machine - * to an external port on the NAT. The NAT should support either the NAT-PMP or the UPnP IGD - * protocol for this API to create a successful mapping. + * to an external port on the NAT. The NAT should support either PCP, NAT-PMP or the + * UPnP/IGD protocol for this API to create a successful mapping. Note that this API + * currently supports IPv4 addresses/mappings only. If the NAT gateway supports PCP and + * returns an IPv6 address (incorrectly, since this API specifically requests IPv4 + * addresses), the DNSServiceNATPortMappingReply callback will be invoked with errorCode + * kDNSServiceErr_NATPortMappingUnsupported. * * The port mapping will be renewed indefinitely until the client process exits, or * explicitly terminates the port mapping request by calling DNSServiceRefDeallocate(). @@ -1890,18 +2159,18 @@ DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord */ typedef void (DNSSD_API *DNSServiceNATPortMappingReply) - ( - DNSServiceRef sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceErrorType errorCode, - uint32_t externalAddress, /* four byte IPv4 address in network byte order */ - DNSServiceProtocol protocol, - uint16_t internalPort, /* In network byte order */ - uint16_t externalPort, /* In network byte order and may be different than the requested port */ - uint32_t ttl, /* may be different than the requested ttl */ +( + DNSServiceRef sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceErrorType errorCode, + uint32_t externalAddress, /* four byte IPv4 address in network byte order */ + DNSServiceProtocol protocol, + uint16_t internalPort, /* In network byte order */ + uint16_t externalPort, /* In network byte order and may be different than the requested port */ + uint32_t ttl, /* may be different than the requested ttl */ void *context - ); +); /* DNSServiceNATPortMappingCreate() Parameters: @@ -1953,25 +2222,26 @@ typedef void (DNSSD_API *DNSServiceNATPortMappingReply) * display) then pass zero for protocol, internalPort, externalPort and ttl. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate - ( +( DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceProtocol protocol, /* TCP and/or UDP */ - uint16_t internalPort, /* network byte order */ - uint16_t externalPort, /* network byte order */ - uint32_t ttl, /* time to live in seconds */ - DNSServiceNATPortMappingReply callBack, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceProtocol protocol, /* TCP and/or UDP */ + uint16_t internalPort, /* network byte order */ + uint16_t externalPort, /* network byte order */ + uint32_t ttl, /* time to live in seconds */ + DNSServiceNATPortMappingReply callBack, void *context /* may be NULL */ - ); +); /********************************************************************************************* - * - * General Utility Functions - * - *********************************************************************************************/ +* +* General Utility Functions +* +*********************************************************************************************/ /* DNSServiceConstructFullName() * @@ -1999,20 +2269,21 @@ DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate * */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceConstructFullName - ( +( char * const fullName, const char * const service, /* may be NULL */ const char * const regtype, const char * const domain - ); +); /********************************************************************************************* - * - * TXT Record Construction Functions - * - *********************************************************************************************/ +* +* TXT Record Construction Functions +* +*********************************************************************************************/ /* * A typical calling sequence for TXT record construction is something like: @@ -2062,8 +2333,8 @@ typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignmen * For most applications, DNS-SD TXT records are generally * less than 100 bytes, so in most cases a simple fixed-sized * 256-byte buffer will be more than sufficient. - * Recommended size limits for DNS-SD TXT Records are discussed in - * + * Recommended size limits for DNS-SD TXT Records are discussed in RFC 6763 + * * * Note: When passing parameters to and from these TXT record APIs, * the key name does not include the '=' character. The '=' character @@ -2079,12 +2350,13 @@ typedef union _TXTRecordRef_t { char PrivateData[16]; char *ForceNaturalAlignmen * the TXTRecordRef. */ +DNSSD_EXPORT void DNSSD_API TXTRecordCreate - ( +( TXTRecordRef *txtRecord, - uint16_t bufferLen, + uint16_t bufferLen, void *buffer - ); +); /* TXTRecordDeallocate() @@ -2097,10 +2369,11 @@ void DNSSD_API TXTRecordCreate * */ +DNSSD_EXPORT void DNSSD_API TXTRecordDeallocate - ( +( TXTRecordRef *txtRecord - ); +); /* TXTRecordSetValue() @@ -2113,8 +2386,8 @@ void DNSSD_API TXTRecordDeallocate * - Present with no value ("key" appears alone) * - Present with empty value ("key=" appears in TXT record) * - Present with non-empty value ("key=value" appears in TXT record) - * For more details refer to "Data Syntax for DNS-SD TXT Records" in - * + * For more details refer to "Data Syntax for DNS-SD TXT Records" in RFC 6763 + * * * txtRecord: A TXTRecordRef initialized by calling TXTRecordCreate(). * @@ -2140,13 +2413,14 @@ void DNSSD_API TXTRecordDeallocate * exceed the available storage. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API TXTRecordSetValue - ( +( TXTRecordRef *txtRecord, const char *key, - uint8_t valueSize, /* may be zero */ + uint8_t valueSize, /* may be zero */ const void *value /* may be NULL */ - ); +); /* TXTRecordRemoveValue() @@ -2163,11 +2437,12 @@ DNSServiceErrorType DNSSD_API TXTRecordSetValue * exist in the TXTRecordRef. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API TXTRecordRemoveValue - ( +( TXTRecordRef *txtRecord, const char *key - ); +); /* TXTRecordGetLength() @@ -2182,10 +2457,11 @@ DNSServiceErrorType DNSSD_API TXTRecordRemoveValue * Returns 0 if the TXTRecordRef is empty. */ +DNSSD_EXPORT uint16_t DNSSD_API TXTRecordGetLength - ( +( const TXTRecordRef *txtRecord - ); +); /* TXTRecordGetBytesPtr() @@ -2199,17 +2475,18 @@ uint16_t DNSSD_API TXTRecordGetLength * to DNSServiceUpdateRecord(). */ +DNSSD_EXPORT const void * DNSSD_API TXTRecordGetBytesPtr - ( +( const TXTRecordRef *txtRecord - ); +); /********************************************************************************************* - * - * TXT Record Parsing Functions - * - *********************************************************************************************/ +* +* TXT Record Parsing Functions +* +*********************************************************************************************/ /* * A typical calling sequence for TXT record parsing is something like: @@ -2253,12 +2530,13 @@ const void * DNSSD_API TXTRecordGetBytesPtr * Otherwise, it returns 0. */ +DNSSD_EXPORT int DNSSD_API TXTRecordContainsKey - ( - uint16_t txtLen, +( + uint16_t txtLen, const void *txtRecord, const char *key - ); +); /* TXTRecordGetValuePtr() @@ -2282,13 +2560,14 @@ int DNSSD_API TXTRecordContainsKey * For non-empty value, valueLen will be length of value data. */ +DNSSD_EXPORT const void * DNSSD_API TXTRecordGetValuePtr - ( - uint16_t txtLen, +( + uint16_t txtLen, const void *txtRecord, const char *key, uint8_t *valueLen - ); +); /* TXTRecordGetCount() @@ -2304,11 +2583,12 @@ const void * DNSSD_API TXTRecordGetValuePtr * */ +DNSSD_EXPORT uint16_t DNSSD_API TXTRecordGetCount - ( - uint16_t txtLen, +( + uint16_t txtLen, const void *txtRecord - ); +); /* TXTRecordGetItemAtIndex() @@ -2349,71 +2629,85 @@ uint16_t DNSSD_API TXTRecordGetCount * TXTRecordGetCount()-1. */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex - ( - uint16_t txtLen, +( + uint16_t txtLen, const void *txtRecord, - uint16_t itemIndex, - uint16_t keyBufLen, + uint16_t itemIndex, + uint16_t keyBufLen, char *key, uint8_t *valueLen, const void **value - ); +); #if _DNS_SD_LIBDISPATCH /* -* DNSServiceSetDispatchQueue -* -* Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous -* callbacks. It's the clients responsibility to ensure that the provided dispatch queue is running. -* -* A typical application that uses CFRunLoopRun or dispatch_main on its main thread will -* usually schedule DNSServiceRefs on its main queue (which is always a serial queue) -* using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());" -* -* If there is any error during the processing of events, the application callback will -* be called with an error code. For shared connections, each subordinate DNSServiceRef -* will get its own error callback. Currently these error callbacks only happen -* if the mDNSResponder daemon is manually terminated or crashes, and the error -* code in this case is kDNSServiceErr_ServiceNotRunning. The application must call -* DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code. -* These error callbacks are rare and should not normally happen on customer machines, -* but application code should be written defensively to handle such error callbacks -* gracefully if they occur. -* -* After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult -* on the same DNSServiceRef will result in undefined behavior and should be avoided. -* -* Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using -* DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use -* DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch -* queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until -* the application no longer requires that operation and terminates it using DNSServiceRefDeallocate. -* -* service: DNSServiceRef that was allocated and returned to the application, when the -* application calls one of the DNSService API. -* -* queue: dispatch queue where the application callback will be scheduled -* -* return value: Returns kDNSServiceErr_NoError on success. -* Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source -* Returns kDNSServiceErr_BadParam if the service param is invalid or the -* queue param is invalid -*/ + * DNSServiceSetDispatchQueue + * + * Allows you to schedule a DNSServiceRef on a serial dispatch queue for receiving asynchronous + * callbacks. It's the clients responsibility to ensure that the provided dispatch queue is running. + * + * A typical application that uses CFRunLoopRun or dispatch_main on its main thread will + * usually schedule DNSServiceRefs on its main queue (which is always a serial queue) + * using "DNSServiceSetDispatchQueue(sdref, dispatch_get_main_queue());" + * + * If there is any error during the processing of events, the application callback will + * be called with an error code. For shared connections, each subordinate DNSServiceRef + * will get its own error callback. Currently these error callbacks only happen + * if the daemon is manually terminated or crashes, and the error + * code in this case is kDNSServiceErr_ServiceNotRunning. The application must call + * DNSServiceRefDeallocate to free the DNSServiceRef when it gets such an error code. + * These error callbacks are rare and should not normally happen on customer machines, + * but application code should be written defensively to handle such error callbacks + * gracefully if they occur. + * + * After using DNSServiceSetDispatchQueue on a DNSServiceRef, calling DNSServiceProcessResult + * on the same DNSServiceRef will result in undefined behavior and should be avoided. + * + * Once the application successfully schedules a DNSServiceRef on a serial dispatch queue using + * DNSServiceSetDispatchQueue, it cannot remove the DNSServiceRef from the dispatch queue, or use + * DNSServiceSetDispatchQueue a second time to schedule the DNSServiceRef onto a different serial dispatch + * queue. Once scheduled onto a dispatch queue a DNSServiceRef will deliver events to that queue until + * the application no longer requires that operation and terminates it using DNSServiceRefDeallocate. + * + * service: DNSServiceRef that was allocated and returned to the application, when the + * application calls one of the DNSService API. + * + * queue: dispatch queue where the application callback will be scheduled + * + * return value: Returns kDNSServiceErr_NoError on success. + * Returns kDNSServiceErr_NoMemory if it cannot create a dispatch source + * Returns kDNSServiceErr_BadParam if the service param is invalid or the + * queue param is invalid + */ +DNSSD_EXPORT DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue - ( - DNSServiceRef service, - dispatch_queue_t queue - ); +( + DNSServiceRef service, + dispatch_queue_t queue +); #endif //_DNS_SD_LIBDISPATCH -#ifdef __APPLE_API_PRIVATE - -#define kDNSServiceCompPrivateDNS "PrivateDNS" -#define kDNSServiceCompMulticastDNS "MulticastDNS" - -#endif //__APPLE_API_PRIVATE +#if !defined(_WIN32) +typedef void (DNSSD_API *DNSServiceSleepKeepaliveReply) +( + DNSServiceRef sdRef, + DNSServiceErrorType errorCode, + void *context +); +DNSSD_EXPORT +DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + int fd, + unsigned int timeout, + DNSServiceSleepKeepaliveReply callBack, + void *context +); +#endif /* Some C compiler cleverness. We can make the compiler check certain things for us, * and report errors at compile-time if anything is wrong. The usual way to do this would @@ -2423,12 +2717,12 @@ DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue */ struct CompileTimeAssertionChecks_DNS_SD - { +{ char assert0[(sizeof(union _TXTRecordRef_t) == 16) ? 1 : -1]; - }; +}; #ifdef __cplusplus - } +} #endif #endif /* _DNS_SD_H */ diff --git a/bonjour-sdk/dnssd_clientlib.c b/bonjour-sdk/dnssd_clientlib.c index c3a3cfc..2a1f5ed 100644 --- a/bonjour-sdk/dnssd_clientlib.c +++ b/bonjour-sdk/dnssd_clientlib.c @@ -1,28 +1,28 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2004-2018 Apple Inc. All rights reserved. * - * Redistribution and use in source and binary forms, with or without + * 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 Apple Computer, Inc. ("Apple") nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. + * 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 Apple Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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 + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS 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 APPLE OR ITS 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. */ @@ -31,22 +31,18 @@ #include "dns_sd.h" -#if MDNS_BUILDINGSHAREDLIBRARY || MDNS_BUILDINGSTUBLIBRARY -#pragma export on -#endif - #if defined(_WIN32) // disable warning "conversion from to uint16_t" #pragma warning(disable:4244) #define strncasecmp _strnicmp -#define strcasecmp _stricmp +#define strcasecmp _stricmp #endif /********************************************************************************************* - * - * Supporting Functions - * - *********************************************************************************************/ +* +* Supporting Functions +* +*********************************************************************************************/ #define mDNSIsDigit(X) ((X) >= '0' && (X) <= '9') @@ -54,313 +50,321 @@ // (DNSServiceConstructFullName depends this returning 1 for true, rather than any non-zero value meaning true) static int DomainEndsInDot(const char *dom) - { - while (dom[0] && dom[1]) - { - if (dom[0] == '\\') // advance past escaped byte sequence - { - if (mDNSIsDigit(dom[1]) && mDNSIsDigit(dom[2]) && mDNSIsDigit(dom[3])) - dom += 4; // If "\ddd" then skip four - else dom += 2; // else if "\x" then skip two - } - else dom++; // else goto next character - } - return (dom[0] == '.'); - } +{ + while (dom[0] && dom[1]) + { + if (dom[0] == '\\') // advance past escaped byte sequence + { + if (mDNSIsDigit(dom[1]) && mDNSIsDigit(dom[2]) && mDNSIsDigit(dom[3])) + dom += 4; // If "\ddd" then skip four + else dom += 2; // else if "\x" then skip two + } + else dom++; // else goto next character + } + return (dom[0] == '.'); +} static uint8_t *InternalTXTRecordSearch - ( - uint16_t txtLen, - const void *txtRecord, - const char *key, - unsigned long *keylen - ) - { - uint8_t *p = (uint8_t*)txtRecord; - uint8_t *e = p + txtLen; - *keylen = (unsigned long) strlen(key); - while (p= lim) goto fail; - *fn++ = '\\'; - *fn++ = '0' + (c / 100); - *fn++ = '0' + (c / 10) % 10; - c = '0' + (c ) % 10; - } - else if (c == '.' || (c == '\\')) // Escape dot and backslash literals - { - if (fn+2 >= lim) goto fail; - *fn++ = '\\'; - } - else - if (fn+1 >= lim) goto fail; - *fn++ = (char)c; - } - *fn++ = '.'; - } + if (service && *service) + { + while (*s) + { + unsigned char c = *s++; // Needs to be unsigned, or values like 0xFF will be interpreted as < 32 + if (c <= ' ') // Escape non-printable characters + { + if (fn+4 >= lim) goto fail; + *fn++ = '\\'; + *fn++ = '0' + (c / 100); + *fn++ = '0' + (c / 10) % 10; + c = '0' + (c ) % 10; + } + else if (c == '.' || (c == '\\')) // Escape dot and backslash literals + { + if (fn+2 >= lim) goto fail; + *fn++ = '\\'; + } + else + if (fn+1 >= lim) goto fail; + *fn++ = (char)c; + } + *fn++ = '.'; + } - while (*r) if (fn+1 >= lim) goto fail; else *fn++ = *r++; - if (!DomainEndsInDot(regtype)) { if (fn+1 >= lim) goto fail; else *fn++ = '.'; } + while (*r) if (fn+1 >= lim) goto fail;else *fn++ = *r++; + if (!DomainEndsInDot(regtype)) { if (fn+1 >= lim) goto fail;else *fn++ = '.';} - while (*d) if (fn+1 >= lim) goto fail; else *fn++ = *d++; - if (!DomainEndsInDot(domain)) { if (fn+1 >= lim) goto fail; else *fn++ = '.'; } + while (*d) if (fn+1 >= lim) goto fail;else *fn++ = *d++; + if (!DomainEndsInDot(domain)) { if (fn+1 >= lim) goto fail;else *fn++ = '.';} - *fn = '\0'; - return kDNSServiceErr_NoError; + *fn = '\0'; + return kDNSServiceErr_NoError; fail: - *fn = '\0'; - return kDNSServiceErr_BadParam; - } + *fn = '\0'; + return kDNSServiceErr_BadParam; +} /********************************************************************************************* - * - * TXT Record Construction Functions - * - *********************************************************************************************/ +* +* TXT Record Construction Functions +* +*********************************************************************************************/ typedef struct _TXTRecordRefRealType - { - uint8_t *buffer; // Pointer to data - uint16_t buflen; // Length of buffer - uint16_t datalen; // Length currently in use - uint16_t malloced; // Non-zero if buffer was allocated via malloc() - } TXTRecordRefRealType; +{ + uint8_t *buffer; // Pointer to data + uint16_t buflen; // Length of buffer + uint16_t datalen; // Length currently in use + uint16_t malloced; // Non-zero if buffer was allocated via malloc() +} TXTRecordRefRealType; #define txtRec ((TXTRecordRefRealType*)txtRecord) // The opaque storage defined in the public dns_sd.h header is 16 bytes; // make sure we don't exceed that. struct CompileTimeAssertionCheck_dnssd_clientlib - { - char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1]; - }; +{ + char assert0[(sizeof(TXTRecordRefRealType) <= 16) ? 1 : -1]; +}; void DNSSD_API TXTRecordCreate - ( - TXTRecordRef *txtRecord, - uint16_t bufferLen, - void *buffer - ) - { - txtRec->buffer = buffer; - txtRec->buflen = buffer ? bufferLen : (uint16_t)0; - txtRec->datalen = 0; - txtRec->malloced = 0; - } +( + TXTRecordRef *txtRecord, + uint16_t bufferLen, + void *buffer +) +{ + txtRec->buffer = buffer; + txtRec->buflen = buffer ? bufferLen : (uint16_t)0; + txtRec->datalen = 0; + txtRec->malloced = 0; +} void DNSSD_API TXTRecordDeallocate(TXTRecordRef *txtRecord) - { - if (txtRec->malloced) free(txtRec->buffer); - } +{ + if (txtRec->malloced) free(txtRec->buffer); +} DNSServiceErrorType DNSSD_API TXTRecordSetValue - ( - TXTRecordRef *txtRecord, - const char *key, - uint8_t valueSize, - const void *value - ) - { - uint8_t *start, *p; - const char *k; - unsigned long keysize, keyvalsize; +( + TXTRecordRef *txtRecord, + const char *key, + uint8_t valueSize, + const void *value +) +{ + uint8_t *start, *p; + const char *k; + unsigned long keysize, keyvalsize; - for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid); - keysize = (unsigned long)(k - key); - keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0); - if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid); - (void)TXTRecordRemoveValue(txtRecord, key); - if (txtRec->datalen + keyvalsize > txtRec->buflen) - { - unsigned char *newbuf; - unsigned long newlen = txtRec->datalen + keyvalsize; - if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid); - newbuf = malloc((size_t)newlen); - if (!newbuf) return(kDNSServiceErr_NoMemory); - memcpy(newbuf, txtRec->buffer, txtRec->datalen); - if (txtRec->malloced) free(txtRec->buffer); - txtRec->buffer = newbuf; - txtRec->buflen = (uint16_t)(newlen); - txtRec->malloced = 1; - } - start = txtRec->buffer + txtRec->datalen; - p = start + 1; - memcpy(p, key, keysize); - p += keysize; - if (value) - { - *p++ = '='; - memcpy(p, value, valueSize); - p += valueSize; - } - *start = (uint8_t)(p - start - 1); - txtRec->datalen += p - start; - return(kDNSServiceErr_NoError); - } + for (k = key; *k; k++) if (*k < 0x20 || *k > 0x7E || *k == '=') return(kDNSServiceErr_Invalid); + keysize = (unsigned long)(k - key); + keyvalsize = 1 + keysize + (value ? (1 + valueSize) : 0); + if (keysize < 1 || keyvalsize > 255) return(kDNSServiceErr_Invalid); + (void)TXTRecordRemoveValue(txtRecord, key); + if (txtRec->datalen + keyvalsize > txtRec->buflen) + { + unsigned char *newbuf; + unsigned long newlen = txtRec->datalen + keyvalsize; + if (newlen > 0xFFFF) return(kDNSServiceErr_Invalid); + newbuf = malloc((size_t)newlen); + if (!newbuf) return(kDNSServiceErr_NoMemory); + memcpy(newbuf, txtRec->buffer, txtRec->datalen); + if (txtRec->malloced) free(txtRec->buffer); + txtRec->buffer = newbuf; + txtRec->buflen = (uint16_t)(newlen); + txtRec->malloced = 1; + } + start = txtRec->buffer + txtRec->datalen; + p = start + 1; + memcpy(p, key, keysize); + p += keysize; + if (value) + { + *p++ = '='; + memcpy(p, value, valueSize); + p += valueSize; + } + *start = (uint8_t)(p - start - 1); + txtRec->datalen += p - start; + return(kDNSServiceErr_NoError); +} DNSServiceErrorType DNSSD_API TXTRecordRemoveValue - ( - TXTRecordRef *txtRecord, - const char *key - ) - { - unsigned long keylen, itemlen, remainder; - uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen); - if (!item) return(kDNSServiceErr_NoSuchKey); - itemlen = (unsigned long)(1 + item[0]); - remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen)); - // Use memmove because memcpy behaviour is undefined for overlapping regions - memmove(item, item + itemlen, remainder); - txtRec->datalen -= itemlen; - return(kDNSServiceErr_NoError); - } +( + TXTRecordRef *txtRecord, + const char *key +) +{ + unsigned long keylen, itemlen, remainder; + uint8_t *item = InternalTXTRecordSearch(txtRec->datalen, txtRec->buffer, key, &keylen); + if (!item) return(kDNSServiceErr_NoSuchKey); + itemlen = (unsigned long)(1 + item[0]); + remainder = (unsigned long)((txtRec->buffer + txtRec->datalen) - (item + itemlen)); + // Use memmove because memcpy behaviour is undefined for overlapping regions + memmove(item, item + itemlen, remainder); + txtRec->datalen -= itemlen; + return(kDNSServiceErr_NoError); +} uint16_t DNSSD_API TXTRecordGetLength (const TXTRecordRef *txtRecord) { return(txtRec->datalen); } const void * DNSSD_API TXTRecordGetBytesPtr(const TXTRecordRef *txtRecord) { return(txtRec->buffer); } /********************************************************************************************* - * - * TXT Record Parsing Functions - * - *********************************************************************************************/ +* +* TXT Record Parsing Functions +* +*********************************************************************************************/ int DNSSD_API TXTRecordContainsKey - ( - uint16_t txtLen, - const void *txtRecord, - const char *key - ) - { - unsigned long keylen; - return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0); - } +( + uint16_t txtLen, + const void *txtRecord, + const char *key +) +{ + unsigned long keylen; + return (InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen) ? 1 : 0); +} const void * DNSSD_API TXTRecordGetValuePtr - ( - uint16_t txtLen, - const void *txtRecord, - const char *key, - uint8_t *valueLen - ) - { - unsigned long keylen; - uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen); - if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL - *valueLen = (uint8_t)(item[0] - (keylen + 1)); - return (item + 1 + keylen + 1); - } +( + uint16_t txtLen, + const void *txtRecord, + const char *key, + uint8_t *valueLen +) +{ + unsigned long keylen; + uint8_t *item = InternalTXTRecordSearch(txtLen, txtRecord, key, &keylen); + if (!item || item[0] <= keylen) return(NULL); // If key not found, or found with no value, return NULL + *valueLen = (uint8_t)(item[0] - (keylen + 1)); + return (item + 1 + keylen + 1); +} uint16_t DNSSD_API TXTRecordGetCount - ( - uint16_t txtLen, - const void *txtRecord - ) - { - uint16_t count = 0; - uint8_t *p = (uint8_t*)txtRecord; - uint8_t *e = p + txtLen; - while (pe) ? (uint16_t)0 : count); - } +( + uint16_t txtLen, + const void *txtRecord +) +{ + uint16_t count = 0; + uint8_t *p = (uint8_t*)txtRecord; + uint8_t *e = p + txtLen; + while (pe) ? (uint16_t)0 : count); +} DNSServiceErrorType DNSSD_API TXTRecordGetItemAtIndex - ( - uint16_t txtLen, - const void *txtRecord, - uint16_t itemIndex, - uint16_t keyBufLen, - char *key, - uint8_t *valueLen, - const void **value - ) - { - uint16_t count = 0; - uint8_t *p = (uint8_t*)txtRecord; - uint8_t *e = p + txtLen; - while (p= keyBufLen) return(kDNSServiceErr_NoMemory); - memcpy(key, x, len); - key[len] = 0; - if (x+len= keyBufLen) return(kDNSServiceErr_NoMemory); + memcpy(key, x, len); + key[len] = 0; + if (x+len #include -#if APPLE_OSX_mDNSResponder -#include -#endif - #include "dnssd_ipc.h" -static int gDaemonErr = kDNSServiceErr_NoError; +#if APPLE_OSX_mDNSResponder +#include +#include +#include +#include "dns_sd_internal.h" +#endif #if defined(_WIN32) - #define _SSIZE_T - #include - #include - #include - #include - #include - #include - #include - - #define sockaddr_mdns sockaddr_in - #define AF_MDNS AF_INET - - // Disable warning: "'type cast' : from data pointer 'void *' to function pointer" - #pragma warning(disable:4055) - - // Disable warning: "nonstandard extension, function/data pointer conversion in expression" - #pragma warning(disable:4152) - - extern BOOL IsSystemServiceDisabled(); - - #define sleep(X) Sleep((X) * 1000) - - static int g_initWinsock = 0; - #define LOG_WARNING kDebugLevelWarning - #define LOG_INFO kDebugLevelInfo - static void syslog( int priority, const char * message, ...) - { - va_list args; - int len; - char * buffer; - DWORD err = WSAGetLastError(); - (void) priority; - va_start( args, message ); - len = _vscprintf( message, args ) + 1; - buffer = malloc( len * sizeof(char) ); - if ( buffer ) { vsprintf( buffer, message, args ); OutputDebugString( buffer ); free( buffer ); } - WSASetLastError( err ); - } + #define _SSIZE_T + #include + #include + #include + #include + #include + #include + #include + + #define sockaddr_mdns sockaddr_in + #define AF_MDNS AF_INET + +// Disable warning: "'type cast' : from data pointer 'void *' to function pointer" + #pragma warning(disable:4055) + +// Disable warning: "nonstandard extension, function/data pointer conversion in expression" + #pragma warning(disable:4152) + +extern BOOL IsSystemServiceDisabled(); + + #define sleep(X) Sleep((X) * 1000) + +static int g_initWinsock = 0; + #define LOG_WARNING kDebugLevelWarning + #define LOG_INFO kDebugLevelInfo +static void syslog( int priority, const char * message, ...) +{ + va_list args; + int len; + char * buffer; + DWORD err = WSAGetLastError(); + (void) priority; + va_start( args, message ); + len = _vscprintf( message, args ) + 1; + buffer = malloc( len * sizeof(char) ); + if ( buffer ) { vsnprintf( buffer, len, message, args ); OutputDebugString( buffer ); free( buffer ); } + WSASetLastError( err ); +} #else - #include // For O_RDWR etc. - #include - #include - #include - - #define sockaddr_mdns sockaddr_un - #define AF_MDNS AF_LOCAL + #include // For O_RDWR etc. + #include + #include + #include + + #define sockaddr_mdns sockaddr_un + #define AF_MDNS AF_LOCAL #endif @@ -96,23 +97,35 @@ static int gDaemonErr = kDNSServiceErr_NoError; // Uncomment the line below to use the old error return mechanism of creating a temporary named socket (e.g. in /var/tmp) //#define USE_NAMED_ERROR_RETURN_SOCKET 1 -#define DNSSD_CLIENT_TIMEOUT 10 // In seconds +// If the UDS client has not received a response from the daemon in 60 secs, it is unlikely to get one +// Note: Timeout of 3 secs should be sufficient in normal scenarios, but 60 secs is chosen as a safeguard since +// some clients may come up before mDNSResponder itself after a BOOT and on rare ocassions IOPM/Keychain/D2D calls +// in mDNSResponder's INIT may take a much longer time to return +#define DNSSD_CLIENT_TIMEOUT 60 #ifndef CTL_PATH_PREFIX #define CTL_PATH_PREFIX "/var/tmp/dnssd_result_socket." #endif typedef struct - { - ipc_msg_hdr ipc_hdr; - DNSServiceFlags cb_flags; - uint32_t cb_interface; - DNSServiceErrorType cb_err; - } CallbackHeader; +{ + ipc_msg_hdr ipc_hdr; + DNSServiceFlags cb_flags; + uint32_t cb_interface; + DNSServiceErrorType cb_err; +} CallbackHeader; typedef struct _DNSServiceRef_t DNSServiceOp; typedef struct _DNSRecordRef_t DNSRecord; +#if !defined(_WIN32) +typedef struct +{ + void *AppCallback; // Client callback function and context + void *AppContext; +} SleepKAContext; +#endif + // client stub callback to process message from server and deliver results to client application typedef void (*ProcessReplyFn)(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *msg, const char *const end); @@ -126,187 +139,218 @@ typedef void (*ProcessReplyFn)(DNSServiceOp *const sdr, const CallbackHeader *co // _DNS_SD_LIBDISPATCH is defined where libdispatch/GCD is available. This does not mean that the application will use the // DNSServiceSetDispatchQueue API. Hence any new code guarded with _DNS_SD_LIBDISPATCH should still be backwards compatible. struct _DNSServiceRef_t - { - DNSServiceOp *next; // For shared connection - DNSServiceOp *primary; // For shared connection - dnssd_sock_t sockfd; // Connected socket between client and daemon - dnssd_sock_t validator; // Used to detect memory corruption, double disposals, etc. - client_context_t uid; // For shared connection requests, each subordinate DNSServiceRef has its own ID, - // unique within the scope of the same shared parent DNSServiceRef - uint32_t op; // request_op_t or reply_op_t - uint32_t max_index; // Largest assigned record index - 0 if no additional records registered - uint32_t logcounter; // Counter used to control number of syslog messages we write - int *moreptr; // Set while DNSServiceProcessResult working on this particular DNSServiceRef - ProcessReplyFn ProcessReply; // Function pointer to the code to handle received messages - void *AppCallback; // Client callback function and context - void *AppContext; - DNSRecord *rec; +{ + DNSServiceOp *next; // For shared connection + DNSServiceOp *primary; // For shared connection + dnssd_sock_t sockfd; // Connected socket between client and daemon + dnssd_sock_t validator; // Used to detect memory corruption, double disposals, etc. + client_context_t uid; // For shared connection requests, each subordinate DNSServiceRef has its own ID, + // unique within the scope of the same shared parent DNSServiceRef + uint32_t op; // request_op_t or reply_op_t + uint32_t max_index; // Largest assigned record index - 0 if no additional records registered + uint32_t logcounter; // Counter used to control number of syslog messages we write + int *moreptr; // Set while DNSServiceProcessResult working on this particular DNSServiceRef + ProcessReplyFn ProcessReply; // Function pointer to the code to handle received messages + void *AppCallback; // Client callback function and context + void *AppContext; + DNSRecord *rec; #if _DNS_SD_LIBDISPATCH - dispatch_source_t disp_source; - dispatch_queue_t disp_queue; + dispatch_source_t disp_source; + dispatch_queue_t disp_queue; #endif - }; + void *kacontext; +}; struct _DNSRecordRef_t - { - DNSRecord *recnext; - void *AppContext; - DNSServiceRegisterRecordReply AppCallback; - DNSRecordRef recref; - uint32_t record_index; // index is unique to the ServiceDiscoveryRef - DNSServiceOp *sdr; - }; +{ + DNSRecord *recnext; + void *AppContext; + DNSServiceRegisterRecordReply AppCallback; + DNSRecordRef recref; + uint32_t record_index; // index is unique to the ServiceDiscoveryRef + client_context_t uid; // For demultiplexing multiple DNSServiceRegisterRecord calls + DNSServiceOp *sdr; +}; + +#if !defined(USE_TCP_LOOPBACK) +static void SetUDSPath(struct sockaddr_un *saddr, const char *path) +{ + size_t pathLen; + + pathLen = strlen(path); + if (pathLen < sizeof(saddr->sun_path)) + memcpy(saddr->sun_path, path, pathLen + 1); + else + saddr->sun_path[0] = '\0'; +} +#endif // Write len bytes. Return 0 on success, -1 on error static int write_all(dnssd_sock_t sd, char *buf, size_t len) - { - // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. - //if (send(sd, buf, len, MSG_WAITALL) != len) return -1; - while (len) - { - ssize_t num_written = send(sd, buf, (long)len, 0); - if (num_written < 0 || (size_t)num_written > len) - { - // Should never happen. If it does, it indicates some OS bug, - // or that the mDNSResponder daemon crashed (which should never happen). - #if !defined(__ppc__) && defined(SO_ISDEFUNCT) - int defunct; - socklen_t dlen = sizeof (defunct); - if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0) - syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); - if (!defunct) - syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd, - (long)num_written, (long)len, - (num_written < 0) ? dnssd_errno : 0, - (num_written < 0) ? dnssd_strerror(dnssd_errno) : ""); - else - syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd); - #else - syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd, - (long)num_written, (long)len, - (num_written < 0) ? dnssd_errno : 0, - (num_written < 0) ? dnssd_strerror(dnssd_errno) : ""); - #endif - return -1; - } - buf += num_written; - len -= num_written; - } - return 0; - } +{ + // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. + //if (send(sd, buf, len, MSG_WAITALL) != len) return -1; + while (len) + { + ssize_t num_written = send(sd, buf, (long)len, 0); + if (num_written < 0 || (size_t)num_written > len) + { + // Check whether socket has gone defunct, + // otherwise, an error here indicates some OS bug + // or that the mDNSResponder daemon crashed (which should never happen). +#if !defined(__ppc__) && defined(SO_ISDEFUNCT) + int defunct = 0; + socklen_t dlen = sizeof (defunct); + if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0) + syslog(LOG_WARNING, "dnssd_clientstub write_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); + if (!defunct) + syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd, + (long)num_written, (long)len, + (num_written < 0) ? dnssd_errno : 0, + (num_written < 0) ? dnssd_strerror(dnssd_errno) : ""); + else + syslog(LOG_INFO, "dnssd_clientstub write_all(%d) DEFUNCT", sd); +#else + syslog(LOG_WARNING, "dnssd_clientstub write_all(%d) failed %ld/%ld %d %s", sd, + (long)num_written, (long)len, + (num_written < 0) ? dnssd_errno : 0, + (num_written < 0) ? dnssd_strerror(dnssd_errno) : ""); +#endif + return -1; + } + buf += num_written; + len -= num_written; + } + return 0; +} enum { read_all_success = 0, read_all_fail = -1, read_all_wouldblock = -2 }; // Read len bytes. Return 0 on success, read_all_fail on error, or read_all_wouldblock for static int read_all(dnssd_sock_t sd, char *buf, int len) - { - // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. - //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1; +{ + // Don't use "MSG_WAITALL"; it returns "Invalid argument" on some Linux versions; use an explicit while() loop instead. + //if (recv(sd, buf, len, MSG_WAITALL) != len) return -1; - while (len) - { - ssize_t num_read = recv(sd, buf, len, 0); - // It is valid to get an interrupted system call error e.g., somebody attaching - // in a debugger, retry without failing - if ((num_read < 0) && (errno == EINTR)) { syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); continue; } - if ((num_read == 0) || (num_read < 0) || (num_read > len)) - { - int printWarn = 0; - int defunct = 0; - // Should never happen. If it does, it indicates some OS bug, - // or that the mDNSResponder daemon crashed (which should never happen). + while (len) + { + ssize_t num_read = recv(sd, buf, len, 0); + // It is valid to get an interrupted system call error e.g., somebody attaching + // in a debugger, retry without failing + if ((num_read < 0) && (errno == EINTR)) + { + syslog(LOG_INFO, "dnssd_clientstub read_all: EINTR continue"); + continue; + } + if ((num_read == 0) || (num_read < 0) || (num_read > len)) + { + int printWarn = 0; + int defunct = 0; + + // Check whether socket has gone defunct, + // otherwise, an error here indicates some OS bug + // or that the mDNSResponder daemon crashed (which should never happen). #if defined(WIN32) - // Suppress logs for "A non-blocking socket operation - // could not be completed immediately" - if (WSAGetLastError() != WSAEWOULDBLOCK) - printWarn = 1; + // Suppress logs for "A non-blocking socket operation + // could not be completed immediately" + if (WSAGetLastError() != WSAEWOULDBLOCK) + printWarn = 1; #endif #if !defined(__ppc__) && defined(SO_ISDEFUNCT) - { - socklen_t dlen = sizeof (defunct); - if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0) - syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); - } - if (!defunct) - printWarn = 1; + { + socklen_t dlen = sizeof (defunct); + if (getsockopt(sd, SOL_SOCKET, SO_ISDEFUNCT, &defunct, &dlen) < 0) + syslog(LOG_WARNING, "dnssd_clientstub read_all: SO_ISDEFUNCT failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); + } + if (!defunct) + printWarn = 1; #endif - if (printWarn) - syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd, - (long)num_read, (long)len, - (num_read < 0) ? dnssd_errno : 0, - (num_read < 0) ? dnssd_strerror(dnssd_errno) : ""); - else if (defunct) - syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd); - return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail; - } - buf += num_read; - len -= num_read; - } - return read_all_success; - } + if (printWarn) + syslog(LOG_WARNING, "dnssd_clientstub read_all(%d) failed %ld/%ld %d %s", sd, + (long)num_read, (long)len, + (num_read < 0) ? dnssd_errno : 0, + (num_read < 0) ? dnssd_strerror(dnssd_errno) : ""); + else if (defunct) + syslog(LOG_INFO, "dnssd_clientstub read_all(%d) DEFUNCT", sd); + return (num_read < 0 && dnssd_errno == dnssd_EWOULDBLOCK) ? read_all_wouldblock : read_all_fail; + } + buf += num_read; + len -= num_read; + } + return read_all_success; +} // Returns 1 if more bytes remain to be read on socket descriptor sd, 0 otherwise static int more_bytes(dnssd_sock_t sd) - { - struct timeval tv = { 0, 0 }; - fd_set readfds; - fd_set *fs; - int ret; +{ + struct timeval tv = { 0, 0 }; + fd_set readfds; + fd_set *fs; + int ret; - if (sd < FD_SETSIZE) - { - fs = &readfds; - FD_ZERO(fs); - } - else - { - // Compute the number of integers needed for storing "sd". Internally fd_set is stored - // as an array of ints with one bit for each fd and hence we need to compute - // the number of ints needed rather than the number of bytes. If "sd" is 32, we need - // two ints and not just one. - int nfdbits = sizeof (int) * 8; - int nints = (sd/nfdbits) + 1; - fs = (fd_set *)calloc(nints, sizeof(int)); - if (fs == NULL) { syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); return 0; } - } - FD_SET(sd, fs); - ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv); - if (fs != &readfds) free(fs); - return (ret > 0); - } - -// Wait for daemon to write to socket -static int wait_for_daemon(dnssd_sock_t sock, int timeout) - { -#ifndef WIN32 - // At this point the next operation (accept() or read()) on this socket may block for a few milliseconds waiting - // for the daemon to respond, but that's okay -- the daemon is a trusted service and we know if won't take more - // than a few milliseconds to respond. So we'll forego checking for readability of the socket. - (void) sock; - (void) timeout; +#if defined(_WIN32) + fs = &readfds; + FD_ZERO(fs); + FD_SET(sd, fs); + ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv); #else - // Windows on the other hand suffers from 3rd party software (primarily 3rd party firewall software) that - // interferes with proper functioning of the TCP protocol stack. Because of this and because we depend on TCP - // to communicate with the system service, we want to make sure that the next operation on this socket (accept() or - // read()) doesn't block indefinitely. - if (!gDaemonErr) - { - struct timeval tv; - fd_set set; - - FD_ZERO(&set); - FD_SET(sock, &set); - tv.tv_sec = timeout; - tv.tv_usec = 0; - if (!select((int)(sock + 1), &set, NULL, NULL, &tv)) - { - syslog(LOG_WARNING, "dnssd_clientstub wait_for_daemon timed out"); - gDaemonErr = kDNSServiceErr_Timeout; - } - } + if (sd < FD_SETSIZE) + { + fs = &readfds; + FD_ZERO(fs); + } + else + { + // Compute the number of integers needed for storing "sd". Internally fd_set is stored + // as an array of ints with one bit for each fd and hence we need to compute + // the number of ints needed rather than the number of bytes. If "sd" is 32, we need + // two ints and not just one. + int nfdbits = sizeof (int) * 8; + int nints = (sd/nfdbits) + 1; + fs = (fd_set *)calloc(nints, (size_t)sizeof(int)); + if (fs == NULL) + { + syslog(LOG_WARNING, "dnssd_clientstub more_bytes: malloc failed"); + return 0; + } + } + FD_SET(sd, fs); + ret = select((int)sd+1, fs, (fd_set*)NULL, (fd_set*)NULL, &tv); + if (fs != &readfds) + free(fs); #endif - return gDaemonErr; - } + return (ret > 0); +} + +// set_waitlimit() implements a timeout using select. It is called from deliver_request() before recv() OR accept() +// to ensure the UDS clients are not blocked in these system calls indefinitely. +// Note: Ideally one should never be blocked here, because it indicates either mDNSResponder daemon is not yet up/hung/ +// superbusy/crashed or some other OS bug. For eg: On Windows which suffers from 3rd party software +// (primarily 3rd party firewall software) interfering with proper functioning of the TCP protocol stack it is possible +// the next operation on this socket(recv/accept) is blocked since we depend on TCP to communicate with the system service. +static int set_waitlimit(dnssd_sock_t sock, int timeout) +{ + int gDaemonErr = kDNSServiceErr_NoError; + + // To prevent stack corruption since select does not work with timeout if fds > FD_SETSIZE(1024) + if (!gDaemonErr && sock < FD_SETSIZE) + { + struct timeval tv; + fd_set set; + + FD_ZERO(&set); + FD_SET(sock, &set); + tv.tv_sec = timeout; + tv.tv_usec = 0; + if (!select((int)(sock + 1), &set, NULL, NULL, &tv)) + { + // Ideally one should never hit this case: See comments before set_waitlimit() + syslog(LOG_WARNING, "dnssd_clientstub set_waitlimit:_daemon timed out (%d secs) without any response: Socket %d", timeout, sock); + gDaemonErr = kDNSServiceErr_Timeout; + } + } + return gDaemonErr; +} /* create_hdr * @@ -319,1668 +363,2076 @@ static int wait_for_daemon(dnssd_sock_t sock, int timeout) * data_start is set past this string. */ static ipc_msg_hdr *create_hdr(uint32_t op, size_t *len, char **data_start, int SeparateReturnSocket, DNSServiceOp *ref) - { - char *msg = NULL; - ipc_msg_hdr *hdr; - int datalen; +{ + char *msg = NULL; + ipc_msg_hdr *hdr; + int datalen; #if !defined(USE_TCP_LOOPBACK) - char ctrl_path[64] = ""; // "/var/tmp/dnssd_result_socket.xxxxxxxxxx-xxx-xxxxxx" + char ctrl_path[64] = ""; // "/var/tmp/dnssd_result_socket.xxxxxxxxxx-xxx-xxxxxx" #endif - if (SeparateReturnSocket) - { + if (SeparateReturnSocket) + { #if defined(USE_TCP_LOOPBACK) - *len += 2; // Allocate space for two-byte port number + *len += 2; // Allocate space for two-byte port number #elif defined(USE_NAMED_ERROR_RETURN_SOCKET) - struct timeval tv; - if (gettimeofday(&tv, NULL) < 0) - { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; } - sprintf(ctrl_path, "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(), - (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec)); - *len += strlen(ctrl_path) + 1; + struct timeval tv; + if (gettimeofday(&tv, NULL) < 0) + { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: gettimeofday failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); return NULL; } + snprintf(ctrl_path, sizeof(ctrl_path), "%s%d-%.3lx-%.6lu", CTL_PATH_PREFIX, (int)getpid(), + (unsigned long)(tv.tv_sec & 0xFFF), (unsigned long)(tv.tv_usec)); + *len += strlen(ctrl_path) + 1; #else - *len += 1; // Allocate space for single zero byte (empty C string) + *len += 1; // Allocate space for single zero byte (empty C string) #endif - } + } - datalen = (int) *len; - *len += sizeof(ipc_msg_hdr); + datalen = (int) *len; + *len += sizeof(ipc_msg_hdr); - // Write message to buffer - msg = malloc(*len); - if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; } + // Write message to buffer + msg = malloc(*len); + if (!msg) { syslog(LOG_WARNING, "dnssd_clientstub create_hdr: malloc failed"); return NULL; } - memset(msg, 0, *len); - hdr = (ipc_msg_hdr *)msg; - hdr->version = VERSION; - hdr->datalen = datalen; - hdr->ipc_flags = 0; - hdr->op = op; - hdr->client_context = ref->uid; - hdr->reg_index = 0; - *data_start = msg + sizeof(ipc_msg_hdr); + memset(msg, 0, *len); + hdr = (ipc_msg_hdr *)msg; + hdr->version = VERSION; + hdr->datalen = datalen; + hdr->ipc_flags = 0; + hdr->op = op; + hdr->client_context = ref->uid; + hdr->reg_index = 0; + *data_start = msg + sizeof(ipc_msg_hdr); #if defined(USE_TCP_LOOPBACK) - // Put dummy data in for the port, since we don't know what it is yet. - // The data will get filled in before we send the message. This happens in deliver_request(). - if (SeparateReturnSocket) put_uint16(0, data_start); + // Put dummy data in for the port, since we don't know what it is yet. + // The data will get filled in before we send the message. This happens in deliver_request(). + if (SeparateReturnSocket) put_uint16(0, data_start); #else - if (SeparateReturnSocket) put_string(ctrl_path, data_start); + if (SeparateReturnSocket) put_string(ctrl_path, data_start); #endif - return hdr; - } + return hdr; +} static void FreeDNSRecords(DNSServiceOp *sdRef) - { - DNSRecord *rec = sdRef->rec; - while (rec) - { - DNSRecord *next = rec->recnext; - free(rec); - rec = next; - } - } +{ + DNSRecord *rec = sdRef->rec; + while (rec) + { + DNSRecord *next = rec->recnext; + free(rec); + rec = next; + } +} static void FreeDNSServiceOp(DNSServiceOp *x) - { - // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed - // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket) - if ((x->sockfd ^ x->validator) != ValidatorBits) - syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator); - else - { - x->next = NULL; - x->primary = NULL; - x->sockfd = dnssd_InvalidSocket; - x->validator = 0xDDDDDDDD; - x->op = request_op_none; - x->max_index = 0; - x->logcounter = 0; - x->moreptr = NULL; - x->ProcessReply = NULL; - x->AppCallback = NULL; - x->AppContext = NULL; +{ + // We don't use our DNSServiceRefValid macro here because if we're cleaning up after a socket() call failed + // then sockfd could legitimately contain a failing value (e.g. dnssd_InvalidSocket) + if ((x->sockfd ^ x->validator) != ValidatorBits) + { + static DNSServiceOp *op_were_not_going_to_free_but_we_need_to_fool_the_analyzer; + syslog(LOG_WARNING, "dnssd_clientstub attempt to dispose invalid DNSServiceRef %p %08X %08X", x, x->sockfd, x->validator); + op_were_not_going_to_free_but_we_need_to_fool_the_analyzer = x; + } + else + { + x->next = NULL; + x->primary = NULL; + x->sockfd = dnssd_InvalidSocket; + x->validator = 0xDDDDDDDD; + x->op = request_op_none; + x->max_index = 0; + x->logcounter = 0; + x->moreptr = NULL; + x->ProcessReply = NULL; + x->AppCallback = NULL; + x->AppContext = NULL; #if _DNS_SD_LIBDISPATCH - if (x->disp_source) dispatch_release(x->disp_source); - x->disp_source = NULL; - x->disp_queue = NULL; + if (x->disp_source) dispatch_release(x->disp_source); + x->disp_source = NULL; + x->disp_queue = NULL; #endif - // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord - // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiveRegisterRecord. DNSRecords may have - // been freed if the application called DNSRemoveRecord - FreeDNSRecords(x); - free(x); - } - } + // DNSRecords may have been added to subordinate sdRef e.g., DNSServiceRegister/DNSServiceAddRecord + // or on the main sdRef e.g., DNSServiceCreateConnection/DNSServiceRegisterRecord. + // DNSRecords may have been freed if the application called DNSRemoveRecord. + FreeDNSRecords(x); + if (x->kacontext) + { + free(x->kacontext); + x->kacontext = NULL; + } + free(x); + } +} // Return a connected service ref (deallocate with DNSServiceRefDeallocate) static DNSServiceErrorType ConnectToServer(DNSServiceRef *ref, DNSServiceFlags flags, uint32_t op, ProcessReplyFn ProcessReply, void *AppCallback, void *AppContext) - { - #if APPLE_OSX_mDNSResponder - int NumTries = DNSSD_CLIENT_MAXTRIES; - #else - int NumTries = 0; - #endif +{ + int NumTries = 0; - dnssd_sockaddr_t saddr; - DNSServiceOp *sdr; + dnssd_sockaddr_t saddr; + DNSServiceOp *sdr; - if (!ref) { syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!ref) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSService operation with NULL DNSServiceRef"); + return kDNSServiceErr_BadParam; + } - if (flags & kDNSServiceFlagsShareConnection) - { - if (!*ref) - { - syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef"); - return kDNSServiceErr_BadParam; - } - if (!DNSServiceRefValid(*ref) || (*ref)->op != connection_request || (*ref)->primary) - { - syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X", - (*ref), (*ref)->sockfd, (*ref)->validator); - *ref = NULL; - return kDNSServiceErr_BadReference; - } - } + if (flags & kDNSServiceFlagsShareConnection) + { + if (!*ref) + { + syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with NULL DNSServiceRef"); + return kDNSServiceErr_BadParam; + } + if (!DNSServiceRefValid(*ref) || ((*ref)->op != connection_request && (*ref)->op != connection_delegate_request) || (*ref)->primary) + { + syslog(LOG_WARNING, "dnssd_clientstub kDNSServiceFlagsShareConnection used with invalid DNSServiceRef %p %08X %08X op %d", + (*ref), (*ref)->sockfd, (*ref)->validator, (*ref)->op); + *ref = NULL; + return kDNSServiceErr_BadReference; + } + } - #if defined(_WIN32) - if (!g_initWinsock) - { - WSADATA wsaData; - g_initWinsock = 1; - if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; } - } - // If the system service is disabled, we only want to try to connect once - //if (IsSystemServiceDisabled()) NumTries = DNSSD_CLIENT_MAXTRIES; - #endif + #if defined(_WIN32) + if (!g_initWinsock) + { + WSADATA wsaData; + g_initWinsock = 1; + if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) { *ref = NULL; return kDNSServiceErr_ServiceNotRunning; } + } + // If the system service is disabled, we only want to try to connect once + //if (IsSystemServiceDisabled()) + // NumTries = DNSSD_CLIENT_MAXTRIES; + #endif - sdr = malloc(sizeof(DNSServiceOp)); - if (!sdr) { syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); *ref = NULL; return kDNSServiceErr_NoMemory; } - sdr->next = NULL; - sdr->primary = NULL; - sdr->sockfd = dnssd_InvalidSocket; - sdr->validator = sdr->sockfd ^ ValidatorBits; - sdr->op = op; - sdr->max_index = 0; - sdr->logcounter = 0; - sdr->moreptr = NULL; - sdr->uid.u32[0] = 0; - sdr->uid.u32[1] = 0; - sdr->ProcessReply = ProcessReply; - sdr->AppCallback = AppCallback; - sdr->AppContext = AppContext; - sdr->rec = NULL; + sdr = malloc(sizeof(DNSServiceOp)); + if (!sdr) + { + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: malloc failed"); + *ref = NULL; + return kDNSServiceErr_NoMemory; + } + sdr->next = NULL; + sdr->primary = NULL; + sdr->sockfd = dnssd_InvalidSocket; + sdr->validator = sdr->sockfd ^ ValidatorBits; + sdr->op = op; + sdr->max_index = 0; + sdr->logcounter = 0; + sdr->moreptr = NULL; + sdr->uid.u32[0] = 0; + sdr->uid.u32[1] = 0; + sdr->ProcessReply = ProcessReply; + sdr->AppCallback = AppCallback; + sdr->AppContext = AppContext; + sdr->rec = NULL; #if _DNS_SD_LIBDISPATCH - sdr->disp_source = NULL; - sdr->disp_queue = NULL; + sdr->disp_source = NULL; + sdr->disp_queue = NULL; #endif + sdr->kacontext = NULL; - if (flags & kDNSServiceFlagsShareConnection) - { - DNSServiceOp **p = &(*ref)->next; // Append ourselves to end of primary's list - while (*p) p = &(*p)->next; - *p = sdr; - // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear - if (++(*ref)->uid.u32[0] == 0) ++(*ref)->uid.u32[1]; // In parent DNSServiceOp increment UID counter - sdr->primary = *ref; // Set our primary pointer - sdr->sockfd = (*ref)->sockfd; // Inherit primary's socket - sdr->validator = (*ref)->validator; - sdr->uid = (*ref)->uid; - //printf("ConnectToServer sharing socket %d\n", sdr->sockfd); - } - else - { - #ifdef SO_NOSIGPIPE - const unsigned long optval = 1; - #endif - *ref = NULL; - sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0); - sdr->validator = sdr->sockfd ^ ValidatorBits; - if (!dnssd_SocketValid(sdr->sockfd)) - { - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); - FreeDNSServiceOp(sdr); - return kDNSServiceErr_NoMemory; - } - #ifdef SO_NOSIGPIPE - // Some environments (e.g. OS X) support turning off SIGPIPE for a socket - if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0) - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); - #endif - #if defined(USE_TCP_LOOPBACK) - saddr.sin_family = AF_INET; - saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); - saddr.sin_port = htons(MDNS_TCP_SERVERPORT); - #else - saddr.sun_family = AF_LOCAL; - strcpy(saddr.sun_path, MDNS_UDS_SERVERPATH); - #if !defined(__ppc__) && defined(SO_DEFUNCTOK) - { - int defunct = 1; - if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0) - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); - } - #endif - #endif - - while (1) - { - int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr)); - if (!err) break; // If we succeeded, return sdr - // If we failed, then it may be because the daemon is still launching. - // This can happen for processes that launch early in the boot process, while the - // daemon is still coming up. Rather than fail here, we'll wait a bit and try again. - // If, after four seconds, we still can't connect to the daemon, - // then we give up and return a failure code. - if (++NumTries < DNSSD_CLIENT_MAXTRIES) sleep(1); // Sleep a bit, then try again - else { dnssd_close(sdr->sockfd); FreeDNSServiceOp(sdr); return kDNSServiceErr_ServiceNotRunning; } - } - //printf("ConnectToServer opened socket %d\n", sdr->sockfd); - } + if (flags & kDNSServiceFlagsShareConnection) + { + DNSServiceOp **p = &(*ref)->next; // Append ourselves to end of primary's list + while (*p) + p = &(*p)->next; + *p = sdr; + // Preincrement counter before we use it -- it helps with debugging if we know the all-zeroes ID should never appear + if (++(*ref)->uid.u32[0] == 0) + ++(*ref)->uid.u32[1]; // In parent DNSServiceOp increment UID counter + sdr->primary = *ref; // Set our primary pointer + sdr->sockfd = (*ref)->sockfd; // Inherit primary's socket + sdr->validator = (*ref)->validator; + sdr->uid = (*ref)->uid; + //printf("ConnectToServer sharing socket %d\n", sdr->sockfd); + } + else + { + #ifdef SO_NOSIGPIPE + const unsigned long optval = 1; + #endif + #ifndef USE_TCP_LOOPBACK + char* uds_serverpath = getenv(MDNS_UDS_SERVERPATH_ENVVAR); + if (uds_serverpath == NULL) + uds_serverpath = MDNS_UDS_SERVERPATH; + else if (strlen(uds_serverpath) >= MAX_CTLPATH) + { + uds_serverpath = MDNS_UDS_SERVERPATH; + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: using default path since env len is invalid"); + } + #endif + *ref = NULL; + sdr->sockfd = socket(AF_DNSSD, SOCK_STREAM, 0); + sdr->validator = sdr->sockfd ^ ValidatorBits; + if (!dnssd_SocketValid(sdr->sockfd)) + { + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: socket failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); + FreeDNSServiceOp(sdr); + return kDNSServiceErr_NoMemory; + } + #ifdef SO_NOSIGPIPE + // Some environments (e.g. OS X) support turning off SIGPIPE for a socket + if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval)) < 0) + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_NOSIGPIPE failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); + #endif + #if defined(USE_TCP_LOOPBACK) + saddr.sin_family = AF_INET; + saddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); + saddr.sin_port = htons(MDNS_TCP_SERVERPORT); + #else + saddr.sun_family = AF_LOCAL; + SetUDSPath(&saddr, uds_serverpath); + #if !defined(__ppc__) && defined(SO_DEFUNCTOK) + { + int defunct = 1; + if (setsockopt(sdr->sockfd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0) + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); + } + #endif + #endif + + while (1) + { + int err = connect(sdr->sockfd, (struct sockaddr *) &saddr, sizeof(saddr)); + if (!err) + break; // If we succeeded, return sdr + // If we failed, then it may be because the daemon is still launching. + // This can happen for processes that launch early in the boot process, while the + // daemon is still coming up. Rather than fail here, we wait 1 sec and try again. + // If, after DNSSD_CLIENT_MAXTRIES, we still can't connect to the daemon, + // then we give up and return a failure code. + if (++NumTries < DNSSD_CLIENT_MAXTRIES) + { + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect()-> No of tries: %d", NumTries); + sleep(1); // Sleep a bit, then try again + } + else + { + #if !defined(USE_TCP_LOOPBACK) + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: connect() failed path:%s Socket:%d Err:%d Errno:%d %s", + uds_serverpath, sdr->sockfd, err, dnssd_errno, dnssd_strerror(dnssd_errno)); + #endif + dnssd_close(sdr->sockfd); + FreeDNSServiceOp(sdr); + return kDNSServiceErr_ServiceNotRunning; + } + } + //printf("ConnectToServer opened socket %d\n", sdr->sockfd); + } - *ref = sdr; - return kDNSServiceErr_NoError; - } + *ref = sdr; + return kDNSServiceErr_NoError; +} #define deliver_request_bailout(MSG) \ - do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0) + do { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: %s failed %d (%s)", (MSG), dnssd_errno, dnssd_strerror(dnssd_errno)); goto cleanup; } while(0) static DNSServiceErrorType deliver_request(ipc_msg_hdr *hdr, DNSServiceOp *sdr) - { - uint32_t datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order - #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET) - char *const data = (char *)hdr + sizeof(ipc_msg_hdr); - #endif - dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; - DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases - int MakeSeparateReturnSocket = 0; +{ + uint32_t datalen; + dnssd_sock_t listenfd = dnssd_InvalidSocket, errsd = dnssd_InvalidSocket; + DNSServiceErrorType err = kDNSServiceErr_Unknown; // Default for the "goto cleanup" cases + int MakeSeparateReturnSocket; + #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET) + char *data; + #endif - // Note: need to check hdr->op, not sdr->op. - // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op - // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be - // add_record_request but the parent sdr->op will be connection_request or reg_service_request) - if (sdr->primary || - hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request) - MakeSeparateReturnSocket = 1; + if (!hdr) + { + syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); + return kDNSServiceErr_Unknown; + } + + datalen = hdr->datalen; // We take a copy here because we're going to convert hdr->datalen to network byte order + #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET) + data = (char *)hdr + sizeof(ipc_msg_hdr); + #endif - if (!DNSServiceRefValid(sdr)) - { - syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator); - return kDNSServiceErr_BadReference; - } + // Note: need to check hdr->op, not sdr->op. + // hdr->op contains the code for the specific operation we're currently doing, whereas sdr->op + // contains the original parent DNSServiceOp (e.g. for an add_record_request, hdr->op will be + // add_record_request but the parent sdr->op will be connection_request or reg_service_request) + MakeSeparateReturnSocket = (sdr->primary || + hdr->op == reg_record_request || hdr->op == add_record_request || hdr->op == update_record_request || hdr->op == remove_record_request); - if (!hdr) { syslog(LOG_WARNING, "dnssd_clientstub deliver_request: !hdr"); return kDNSServiceErr_Unknown; } + if (!DNSServiceRefValid(sdr)) + { + if (hdr) + free(hdr); + syslog(LOG_WARNING, "dnssd_clientstub deliver_request: invalid DNSServiceRef %p %08X %08X", sdr, sdr->sockfd, sdr->validator); + return kDNSServiceErr_BadReference; + } - if (MakeSeparateReturnSocket) - { - #if defined(USE_TCP_LOOPBACK) - { - union { uint16_t s; u_char b[2]; } port; - dnssd_sockaddr_t caddr; - dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr); - listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); - if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket"); + if (MakeSeparateReturnSocket) + { + #if defined(USE_TCP_LOOPBACK) + { + union { uint16_t s; u_char b[2]; } port; + dnssd_sockaddr_t caddr; + dnssd_socklen_t len = (dnssd_socklen_t) sizeof(caddr); + listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); + if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("TCP socket"); - caddr.sin_family = AF_INET; - caddr.sin_port = 0; - caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); - if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind"); - if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) deliver_request_bailout("TCP getsockname"); - if (listen(listenfd, 1) < 0) deliver_request_bailout("TCP listen"); - port.s = caddr.sin_port; - data[0] = port.b[0]; // don't switch the byte order, as the - data[1] = port.b[1]; // daemon expects it in network byte order - } - #elif defined(USE_NAMED_ERROR_RETURN_SOCKET) - { - mode_t mask; - int bindresult; - dnssd_sockaddr_t caddr; - listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); - if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket"); + caddr.sin_family = AF_INET; + caddr.sin_port = 0; + caddr.sin_addr.s_addr = inet_addr(MDNS_TCP_SERVERADDR); + if (bind(listenfd, (struct sockaddr*) &caddr, sizeof(caddr)) < 0) deliver_request_bailout("TCP bind"); + if (getsockname(listenfd, (struct sockaddr*) &caddr, &len) < 0) deliver_request_bailout("TCP getsockname"); + if (listen(listenfd, 1) < 0) deliver_request_bailout("TCP listen"); + port.s = caddr.sin_port; + data[0] = port.b[0]; // don't switch the byte order, as the + data[1] = port.b[1]; // daemon expects it in network byte order + } + #elif defined(USE_NAMED_ERROR_RETURN_SOCKET) + { + mode_t mask; + int bindresult; + dnssd_sockaddr_t caddr; + listenfd = socket(AF_DNSSD, SOCK_STREAM, 0); + if (!dnssd_SocketValid(listenfd)) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET socket"); - caddr.sun_family = AF_LOCAL; - // According to Stevens (section 3.2), there is no portable way to - // determine whether sa_len is defined on a particular platform. - #ifndef NOT_HAVE_SA_LEN - caddr.sun_len = sizeof(struct sockaddr_un); - #endif - strcpy(caddr.sun_path, data); - mask = umask(0); - bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)); - umask(mask); - if (bindresult < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind"); - if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen"); - } - #else - { - dnssd_sock_t sp[2]; - if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair"); - else - { - errsd = sp[0]; // We'll read our four-byte error code from sp[0] - listenfd = sp[1]; // We'll send sp[1] to the daemon - #if !defined(__ppc__) && defined(SO_DEFUNCTOK) - { - int defunct = 1; - if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0) - syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); - } - #endif - } - } - #endif - } + caddr.sun_family = AF_LOCAL; + // According to Stevens (section 3.2), there is no portable way to + // determine whether sa_len is defined on a particular platform. + #ifndef NOT_HAVE_SA_LEN + caddr.sun_len = sizeof(struct sockaddr_un); + #endif + SetUDSPath(&caddr, data); + mask = umask(0); + bindresult = bind(listenfd, (struct sockaddr *)&caddr, sizeof(caddr)); + umask(mask); + if (bindresult < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET bind"); + if (listen(listenfd, 1) < 0) deliver_request_bailout("USE_NAMED_ERROR_RETURN_SOCKET listen"); + } + #else + { + dnssd_sock_t sp[2]; + if (socketpair(AF_DNSSD, SOCK_STREAM, 0, sp) < 0) deliver_request_bailout("socketpair"); + else + { + errsd = sp[0]; // We'll read our four-byte error code from sp[0] + listenfd = sp[1]; // We'll send sp[1] to the daemon + #if !defined(__ppc__) && defined(SO_DEFUNCTOK) + { + int defunct = 1; + if (setsockopt(errsd, SOL_SOCKET, SO_DEFUNCTOK, &defunct, sizeof(defunct)) < 0) + syslog(LOG_WARNING, "dnssd_clientstub ConnectToServer: SO_DEFUNCTOK failed %d %s", dnssd_errno, dnssd_strerror(dnssd_errno)); + } + #endif + } + } + #endif + } #if !defined(USE_TCP_LOOPBACK) && !defined(USE_NAMED_ERROR_RETURN_SOCKET) - // If we're going to make a separate error return socket, and pass it to the daemon - // using sendmsg, then we'll hold back one data byte to go with it. - // On some versions of Unix (including Leopard) sending a control message without - // any associated data does not work reliably -- e.g. one particular issue we ran - // into is that if the receiving program is in a kqueue loop waiting to be notified - // of the received message, it doesn't get woken up when the control message arrives. - if (MakeSeparateReturnSocket || sdr->op == send_bpf) datalen--; // Okay to use sdr->op when checking for op == send_bpf + // If we're going to make a separate error return socket, and pass it to the daemon + // using sendmsg, then we'll hold back one data byte to go with it. + // On some versions of Unix (including Leopard) sending a control message without + // any associated data does not work reliably -- e.g. one particular issue we ran + // into is that if the receiving program is in a kqueue loop waiting to be notified + // of the received message, it doesn't get woken up when the control message arrives. + if (MakeSeparateReturnSocket || sdr->op == send_bpf) + datalen--; // Okay to use sdr->op when checking for op == send_bpf #endif - // At this point, our listening socket is set up and waiting, if necessary, for the daemon to connect back to - ConvertHeaderBytes(hdr); - //syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %lu bytes", (unsigned long)(datalen + sizeof(ipc_msg_hdr))); - //if (MakeSeparateReturnSocket) syslog(LOG_WARNING, "dnssd_clientstub deliver_request name is %s", data); + // At this point, our listening socket is set up and waiting, if necessary, for the daemon to connect back to + ConvertHeaderBytes(hdr); + //syslog(LOG_WARNING, "dnssd_clientstub deliver_request writing %lu bytes", (unsigned long)(datalen + sizeof(ipc_msg_hdr))); + //if (MakeSeparateReturnSocket) syslog(LOG_WARNING, "dnssd_clientstub deliver_request name is %s", data); #if TEST_SENDING_ONE_BYTE_AT_A_TIME - unsigned int i; - for (i=0; isockfd, ((char *)hdr)+i, 1) < 0) - { syslog(LOG_WARNING, "write_all (byte %u) failed", i); goto cleanup; } - usleep(10000); - } + unsigned int i; + for (i=0; isockfd, ((char *)hdr)+i, 1) < 0) + { syslog(LOG_WARNING, "write_all (byte %u) failed", i); goto cleanup; } + usleep(10000); + } #else - if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0) - { - // write_all already prints an error message if there is an error writing to - // the socket except for DEFUNCT. Logging here is unnecessary and also wrong - // in the case of DEFUNCT sockets - syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed", - sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr))); - goto cleanup; - } + if (write_all(sdr->sockfd, (char *)hdr, datalen + sizeof(ipc_msg_hdr)) < 0) + { + // write_all already prints an error message if there is an error writing to + // the socket except for DEFUNCT. Logging here is unnecessary and also wrong + // in the case of DEFUNCT sockets + syslog(LOG_INFO, "dnssd_clientstub deliver_request ERROR: write_all(%d, %lu bytes) failed", + sdr->sockfd, (unsigned long)(datalen + sizeof(ipc_msg_hdr))); + goto cleanup; + } #endif - if (!MakeSeparateReturnSocket) errsd = sdr->sockfd; - if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf - { + if (!MakeSeparateReturnSocket) + errsd = sdr->sockfd; + if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf + { #if defined(USE_TCP_LOOPBACK) || defined(USE_NAMED_ERROR_RETURN_SOCKET) - // At this point we may block in accept for a few milliseconds waiting for the daemon to connect back to us, - // but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond. - dnssd_sockaddr_t daddr; - dnssd_socklen_t len = sizeof(daddr); - if ((err = wait_for_daemon(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) goto cleanup; - errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); - if (!dnssd_SocketValid(errsd)) deliver_request_bailout("accept"); + // At this point we may wait in accept for a few milliseconds waiting for the daemon to connect back to us, + // but that's okay -- the daemon should not take more than a few milliseconds to respond. + // set_waitlimit() ensures we do not block indefinitely just in case something is wrong + dnssd_sockaddr_t daddr; + dnssd_socklen_t len = sizeof(daddr); + if ((err = set_waitlimit(listenfd, DNSSD_CLIENT_TIMEOUT)) != kDNSServiceErr_NoError) + goto cleanup; + errsd = accept(listenfd, (struct sockaddr *)&daddr, &len); + if (!dnssd_SocketValid(errsd)) + deliver_request_bailout("accept"); #else -#if APPLE_OSX_mDNSResponder -// On Leopard, the stock definitions of the CMSG_* macros in /usr/include/sys/socket.h, -// while arguably correct in theory, nonetheless in practice produce code that doesn't work on 64-bit machines -// For details see Bonjour API broken for 64-bit apps (SCM_RIGHTS sendmsg fails) -#undef CMSG_DATA -#define CMSG_DATA(cmsg) ((unsigned char *)(cmsg) + (sizeof(struct cmsghdr))) -#undef CMSG_SPACE -#define CMSG_SPACE(l) ((sizeof(struct cmsghdr)) + (l)) -#undef CMSG_LEN -#define CMSG_LEN(l) ((sizeof(struct cmsghdr)) + (l)) -#endif + struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS + struct msghdr msg; + struct cmsghdr *cmsg; + char cbuf[CMSG_SPACE(4 * sizeof(dnssd_sock_t))]; - struct iovec vec = { ((char *)hdr) + sizeof(ipc_msg_hdr) + datalen, 1 }; // Send the last byte along with the SCM_RIGHTS - struct msghdr msg; - struct cmsghdr *cmsg; - char cbuf[CMSG_SPACE(sizeof(dnssd_sock_t))]; + msg.msg_name = 0; + msg.msg_namelen = 0; + msg.msg_iov = &vec; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + if (MakeSeparateReturnSocket || sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf + { + if (sdr->op == send_bpf) + { + int i; + char p[12]; // Room for "/dev/bpf999" with terminating null + for (i=0; i<100; i++) + { + snprintf(p, sizeof(p), "/dev/bpf%d", i); + listenfd = open(p, O_RDWR, 0); + //if (dnssd_SocketValid(listenfd)) syslog(LOG_WARNING, "Sending fd %d for %s", listenfd, p); + if (!dnssd_SocketValid(listenfd) && dnssd_errno != EBUSY) + syslog(LOG_WARNING, "Error opening %s %d (%s)", p, dnssd_errno, dnssd_strerror(dnssd_errno)); + if (dnssd_SocketValid(listenfd) || dnssd_errno != EBUSY) break; + } + } + msg.msg_control = cbuf; + msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t)); - if (sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf - { - int i; - char p[12]; // Room for "/dev/bpf999" with terminating null - for (i=0; i<100; i++) - { - snprintf(p, sizeof(p), "/dev/bpf%d", i); - listenfd = open(p, O_RDWR, 0); - //if (dnssd_SocketValid(listenfd)) syslog(LOG_WARNING, "Sending fd %d for %s", listenfd, p); - if (!dnssd_SocketValid(listenfd) && dnssd_errno != EBUSY) - syslog(LOG_WARNING, "Error opening %s %d (%s)", p, dnssd_errno, dnssd_strerror(dnssd_errno)); - if (dnssd_SocketValid(listenfd) || dnssd_errno != EBUSY) break; - } - } - - msg.msg_name = 0; - msg.msg_namelen = 0; - msg.msg_iov = &vec; - msg.msg_iovlen = 1; - msg.msg_control = cbuf; - msg.msg_controllen = CMSG_LEN(sizeof(dnssd_sock_t)); - msg.msg_flags = 0; - cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(dnssd_sock_t)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; - *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd; + cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_len = CMSG_LEN(sizeof(dnssd_sock_t)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + *((dnssd_sock_t *)CMSG_DATA(cmsg)) = listenfd; + } #if TEST_KQUEUE_CONTROL_MESSAGE_BUG - sleep(1); + sleep(1); #endif #if DEBUG_64BIT_SCM_RIGHTS - syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld", - errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*), - sizeof(struct cmsghdr) + sizeof(dnssd_sock_t), - CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)), - (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf)); + syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d %ld %ld %ld/%ld/%ld/%ld", + errsd, listenfd, sizeof(dnssd_sock_t), sizeof(void*), + sizeof(struct cmsghdr) + sizeof(dnssd_sock_t), + CMSG_LEN(sizeof(dnssd_sock_t)), (long)CMSG_SPACE(sizeof(dnssd_sock_t)), + (long)((char*)CMSG_DATA(cmsg) + 4 - cbuf)); #endif // DEBUG_64BIT_SCM_RIGHTS - if (sendmsg(sdr->sockfd, &msg, 0) < 0) - { - syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)", - errsd, listenfd, dnssd_errno, dnssd_strerror(dnssd_errno)); - err = kDNSServiceErr_Incompatible; - goto cleanup; - } + if (sendmsg(sdr->sockfd, &msg, 0) < 0) + { + syslog(LOG_WARNING, "dnssd_clientstub deliver_request ERROR: sendmsg failed read sd=%d write sd=%d errno %d (%s)", + errsd, listenfd, dnssd_errno, dnssd_strerror(dnssd_errno)); + err = kDNSServiceErr_Incompatible; + goto cleanup; + } #if DEBUG_64BIT_SCM_RIGHTS - syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d okay", errsd, listenfd); + syslog(LOG_WARNING, "dnssd_clientstub sendmsg read sd=%d write sd=%d okay", errsd, listenfd); #endif // DEBUG_64BIT_SCM_RIGHTS #endif - // Close our end of the socketpair *before* blocking in read_all to get the four-byte error code. - // Otherwise, if the daemon closes our socket (or crashes), we block in read_all() forever - // because the socket is not closed (we still have an open reference to it ourselves). - dnssd_close(listenfd); - listenfd = dnssd_InvalidSocket; // Make sure we don't close it a second time in the cleanup handling below - } + // Close our end of the socketpair *before* calling read_all() to get the four-byte error code. + // Otherwise, if the daemon closes our socket (or crashes), we will have to wait for a timeout + // in read_all() because the socket is not closed (we still have an open reference to it) + // Note: listenfd is overwritten in the case of send_bpf above and that will be closed here + // for send_bpf operation. + dnssd_close(listenfd); + listenfd = dnssd_InvalidSocket; // Make sure we don't close it a second time in the cleanup handling below + } - // At this point we may block in read_all for a few milliseconds waiting for the daemon to send us the error code, - // but that's okay -- the daemon is a trusted service and we know if won't take more than a few milliseconds to respond. - if (sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf - err = kDNSServiceErr_NoError; - else if ((err = wait_for_daemon(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError) - { - if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0) - err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us - else - err = ntohl(err); - } - - //syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err); + // At this point we may wait in read_all for a few milliseconds waiting for the daemon to send us the error code, + // but that's okay -- the daemon should not take more than a few milliseconds to respond. + // set_waitlimit() ensures we do not block indefinitely just in case something is wrong + if (sdr->op == send_bpf) // Okay to use sdr->op when checking for op == send_bpf + err = kDNSServiceErr_NoError; + else if ((err = set_waitlimit(errsd, DNSSD_CLIENT_TIMEOUT)) == kDNSServiceErr_NoError) + { + if (read_all(errsd, (char*)&err, (int)sizeof(err)) < 0) + err = kDNSServiceErr_ServiceNotRunning; // On failure read_all will have written a message to syslog for us + else + err = ntohl(err); + } + //syslog(LOG_WARNING, "dnssd_clientstub deliver_request: retrieved error code %d", err); cleanup: - if (MakeSeparateReturnSocket) - { - if (dnssd_SocketValid(listenfd)) dnssd_close(listenfd); - if (dnssd_SocketValid(errsd)) dnssd_close(errsd); + if (MakeSeparateReturnSocket) + { + if (dnssd_SocketValid(listenfd)) dnssd_close(listenfd); + if (dnssd_SocketValid(errsd)) dnssd_close(errsd); #if defined(USE_NAMED_ERROR_RETURN_SOCKET) - // syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removing UDS: %s", data); - if (unlink(data) != 0) - syslog(LOG_WARNING, "dnssd_clientstub WARNING: unlink(\"%s\") failed errno %d (%s)", data, dnssd_errno, dnssd_strerror(dnssd_errno)); - // else syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removed UDS: %s", data); + // syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removing UDS: %s", data); + if (unlink(data) != 0) + syslog(LOG_WARNING, "dnssd_clientstub WARNING: unlink(\"%s\") failed errno %d (%s)", data, dnssd_errno, dnssd_strerror(dnssd_errno)); + // else syslog(LOG_WARNING, "dnssd_clientstub deliver_request: removed UDS: %s", data); #endif - } + } - free(hdr); - return err; - } + free(hdr); + return err; +} -int DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) - { - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; } +dnssd_sock_t DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdRef) +{ + if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with NULL DNSServiceRef"); return dnssd_InvalidSocket; } - if (!DNSServiceRefValid(sdRef)) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with invalid DNSServiceRef %p %08X %08X", - sdRef, sdRef->sockfd, sdRef->validator); - return dnssd_InvalidSocket; - } + if (!DNSServiceRefValid(sdRef)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD called with invalid DNSServiceRef %p %08X %08X", + sdRef, sdRef->sockfd, sdRef->validator); + return dnssd_InvalidSocket; + } - if (sdRef->primary) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef); - return dnssd_InvalidSocket; - } + if (sdRef->primary) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefSockFD undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef); + return dnssd_InvalidSocket; + } - return (int) sdRef->sockfd; - } + return sdRef->sockfd; +} #if _DNS_SD_LIBDISPATCH static void CallbackWithError(DNSServiceRef sdRef, DNSServiceErrorType error) - { - DNSServiceOp *sdr = sdRef; - DNSServiceOp *sdrNext; - DNSRecord *rec; - DNSRecord *recnext; - int morebytes; - - while (sdr) - { - // We can't touch the sdr after the callback as it can be deallocated in the callback - sdrNext = sdr->next; - morebytes = 1; - sdr->moreptr = &morebytes; - switch (sdr->op) - { - case resolve_request: - if (sdr->AppCallback)((DNSServiceResolveReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, sdr->AppContext); - break; - case query_request: - if (sdr->AppCallback)((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext); - break; - case addrinfo_request: - if (sdr->AppCallback)((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0, sdr->AppContext); - break; - case browse_request: - if (sdr->AppCallback)((DNSServiceBrowseReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL, sdr->AppContext); - break; - case reg_service_request: - if (sdr->AppCallback)((DNSServiceRegisterReply) sdr->AppCallback)(sdr, 0, error, NULL, 0, NULL, sdr->AppContext); - break; - case enumeration_request: - if (sdr->AppCallback)((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, sdr->AppContext); - break; - case connection_request: - // This means Register Record, walk the list of DNSRecords to do the callback - rec = sdr->rec; - while (rec) - { - recnext = rec->recnext; - if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext); - // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records. - // Detect that and return early - if (!morebytes){syslog(LOG_WARNING, "dnssdclientstub:Record: CallbackwithError morebytes zero"); return;} - rec = recnext; - } - break; - case port_mapping_request: - if (sdr->AppCallback)((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext); - break; - default: - syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op); - } - // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. It means - // all other sdrefs have been freed. This happens for shared connections where the - // DNSServiceRefDeallocate on the first sdRef frees all other sdrefs. - if (!morebytes){syslog(LOG_WARNING, "dnssdclientstub:sdRef: CallbackwithError morebytes zero"); return;} - sdr = sdrNext; - } - } +{ + DNSServiceOp *sdr = sdRef; + DNSServiceOp *sdrNext; + DNSRecord *rec; + DNSRecord *recnext; + int morebytes; + + while (sdr) + { + // We can't touch the sdr after the callback as it can be deallocated in the callback + sdrNext = sdr->next; + morebytes = 1; + sdr->moreptr = &morebytes; + switch (sdr->op) + { + case resolve_request: + if (sdr->AppCallback) ((DNSServiceResolveReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, sdr->AppContext); + break; + case query_request: + if (sdr->AppCallback) ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdr->AppContext); + break; + case addrinfo_request: + if (sdr->AppCallback) ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, 0, 0, error, NULL, NULL, 0, sdr->AppContext); + break; + case browse_request: + if (sdr->AppCallback) ((DNSServiceBrowseReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, 0, NULL, sdr->AppContext); + break; + case reg_service_request: + if (sdr->AppCallback) ((DNSServiceRegisterReply) sdr->AppCallback)(sdr, 0, error, NULL, 0, NULL, sdr->AppContext); + break; + case enumeration_request: + if (sdr->AppCallback) ((DNSServiceDomainEnumReply) sdr->AppCallback)(sdr, 0, 0, error, NULL, sdr->AppContext); + break; + case connection_request: + case connection_delegate_request: + // This means Register Record, walk the list of DNSRecords to do the callback + rec = sdr->rec; + while (rec) + { + recnext = rec->recnext; + if (rec->AppCallback) ((DNSServiceRegisterRecordReply)rec->AppCallback)(sdr, 0, 0, error, rec->AppContext); + // The Callback can call DNSServiceRefDeallocate which in turn frees sdr and all the records. + // Detect that and return early + if (!morebytes) {syslog(LOG_WARNING, "dnssdclientstub:Record: CallbackwithError morebytes zero"); return;} + rec = recnext; + } + break; + case port_mapping_request: + if (sdr->AppCallback) ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, 0, 0, error, 0, 0, 0, 0, 0, sdr->AppContext); + break; + default: + syslog(LOG_WARNING, "dnssd_clientstub CallbackWithError called with bad op %d", sdr->op); + } + // If DNSServiceRefDeallocate was called in the callback, morebytes will be zero. As the sdRef + // (and its subordinates) have been freed, we should not proceed further. Note that when we + // call the callback with a subordinate sdRef the application can call DNSServiceRefDeallocate + // on the main sdRef and DNSServiceRefDeallocate handles this case by walking all the sdRefs and + // clears the moreptr so that we can terminate here. + // + // If DNSServiceRefDeallocate was not called in the callback, then set moreptr to NULL so that + // we don't access the stack variable after we return from this function. + if (!morebytes) {syslog(LOG_WARNING, "dnssdclientstub:sdRef: CallbackwithError morebytes zero sdr %p", sdr); return;} + else {sdr->moreptr = NULL;} + sdr = sdrNext; + } +} #endif // _DNS_SD_LIBDISPATCH // Handle reply from server, calling application client callback. If there is no reply // from the daemon on the socket contained in sdRef, the call will block. DNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdRef) - { - int morebytes = 0; +{ + int morebytes = 0; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } - if (!DNSServiceRefValid(sdRef)) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); - return kDNSServiceErr_BadReference; - } + if (!DNSServiceRefValid(sdRef)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); + return kDNSServiceErr_BadReference; + } - if (sdRef->primary) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef); - return kDNSServiceErr_BadReference; - } + if (sdRef->primary) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult undefined for kDNSServiceFlagsShareConnection subordinate DNSServiceRef %p", sdRef); + return kDNSServiceErr_BadReference; + } - if (!sdRef->ProcessReply) - { - static int num_logs = 0; - if (num_logs < 10) syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function"); - if (num_logs < 1000) num_logs++; else sleep(1); - return kDNSServiceErr_BadReference; - } + if (!sdRef->ProcessReply) + { + static int num_logs = 0; + if (num_logs < 10) syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult called with DNSServiceRef with no ProcessReply function"); + if (num_logs < 1000) num_logs++;else sleep(1); + return kDNSServiceErr_BadReference; + } - do - { - CallbackHeader cbh; - char *data; - - // return NoError on EWOULDBLOCK. This will handle the case - // where a non-blocking socket is told there is data, but it was a false positive. - // On error, read_all will write a message to syslog for us, so don't need to duplicate that here - // Note: If we want to properly support using non-blocking sockets in the future - int result = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr)); - if (result == read_all_fail) - { - // Set the ProcessReply to NULL before callback as the sdRef can get deallocated - // in the callback. - sdRef->ProcessReply = NULL; + do + { + CallbackHeader cbh; + char *data; + + // return NoError on EWOULDBLOCK. This will handle the case + // where a non-blocking socket is told there is data, but it was a false positive. + // On error, read_all will write a message to syslog for us, so don't need to duplicate that here + // Note: If we want to properly support using non-blocking sockets in the future + int result = read_all(sdRef->sockfd, (void *)&cbh.ipc_hdr, sizeof(cbh.ipc_hdr)); + if (result == read_all_fail) + { + // Set the ProcessReply to NULL before callback as the sdRef can get deallocated + // in the callback. + sdRef->ProcessReply = NULL; #if _DNS_SD_LIBDISPATCH - // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult - // is not called by the application and hence need to communicate the error. Cancel the - // source so that we don't get any more events - if (sdRef->disp_source) - { - dispatch_source_cancel(sdRef->disp_source); - dispatch_release(sdRef->disp_source); - sdRef->disp_source = NULL; - CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning); - } + // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult + // is not called by the application and hence need to communicate the error. Cancel the + // source so that we don't get any more events + // Note: read_all fails if we could not read from the daemon which can happen if the + // daemon dies or the file descriptor is disconnected (defunct). + if (sdRef->disp_source) + { + dispatch_source_cancel(sdRef->disp_source); + dispatch_release(sdRef->disp_source); + sdRef->disp_source = NULL; + CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning); + } #endif - // Don't touch sdRef anymore as it might have been deallocated - return kDNSServiceErr_ServiceNotRunning; - } - else if (result == read_all_wouldblock) - { - if (morebytes && sdRef->logcounter < 100) - { - sdRef->logcounter++; - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult error: select indicated data was waiting but read_all returned EWOULDBLOCK"); - } - return kDNSServiceErr_NoError; - } - - ConvertHeaderBytes(&cbh.ipc_hdr); - if (cbh.ipc_hdr.version != VERSION) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult daemon version %d does not match client version %d", cbh.ipc_hdr.version, VERSION); - sdRef->ProcessReply = NULL; - return kDNSServiceErr_Incompatible; - } - - data = malloc(cbh.ipc_hdr.datalen); - if (!data) return kDNSServiceErr_NoMemory; - if (read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen) < 0) // On error, read_all will write a message to syslog for us - { - // Set the ProcessReply to NULL before callback as the sdRef can get deallocated - // in the callback. - sdRef->ProcessReply = NULL; + // Don't touch sdRef anymore as it might have been deallocated + return kDNSServiceErr_ServiceNotRunning; + } + else if (result == read_all_wouldblock) + { + if (morebytes && sdRef->logcounter < 100) + { + sdRef->logcounter++; + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult error: select indicated data was waiting but read_all returned EWOULDBLOCK"); + } + return kDNSServiceErr_NoError; + } + + ConvertHeaderBytes(&cbh.ipc_hdr); + if (cbh.ipc_hdr.version != VERSION) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceProcessResult daemon version %d does not match client version %d", cbh.ipc_hdr.version, VERSION); + sdRef->ProcessReply = NULL; + return kDNSServiceErr_Incompatible; + } + + data = malloc(cbh.ipc_hdr.datalen); + if (!data) return kDNSServiceErr_NoMemory; + if (read_all(sdRef->sockfd, data, cbh.ipc_hdr.datalen) < 0) // On error, read_all will write a message to syslog for us + { + // Set the ProcessReply to NULL before callback as the sdRef can get deallocated + // in the callback. + sdRef->ProcessReply = NULL; #if _DNS_SD_LIBDISPATCH - // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult - // is not called by the application and hence need to communicate the error. Cancel the - // source so that we don't get any more events - if (sdRef->disp_source) - { - dispatch_source_cancel(sdRef->disp_source); - dispatch_release(sdRef->disp_source); - sdRef->disp_source = NULL; - CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning); - } + // Call the callbacks with an error if using the dispatch API, as DNSServiceProcessResult + // is not called by the application and hence need to communicate the error. Cancel the + // source so that we don't get any more events + if (sdRef->disp_source) + { + dispatch_source_cancel(sdRef->disp_source); + dispatch_release(sdRef->disp_source); + sdRef->disp_source = NULL; + CallbackWithError(sdRef, kDNSServiceErr_ServiceNotRunning); + } #endif - // Don't touch sdRef anymore as it might have been deallocated - free(data); - return kDNSServiceErr_ServiceNotRunning; - } - else - { - const char *ptr = data; - cbh.cb_flags = get_flags (&ptr, data + cbh.ipc_hdr.datalen); - cbh.cb_interface = get_uint32 (&ptr, data + cbh.ipc_hdr.datalen); - cbh.cb_err = get_error_code(&ptr, data + cbh.ipc_hdr.datalen); + // Don't touch sdRef anymore as it might have been deallocated + free(data); + return kDNSServiceErr_ServiceNotRunning; + } + else + { + const char *ptr = data; + cbh.cb_flags = get_flags (&ptr, data + cbh.ipc_hdr.datalen); + cbh.cb_interface = get_uint32 (&ptr, data + cbh.ipc_hdr.datalen); + cbh.cb_err = get_error_code(&ptr, data + cbh.ipc_hdr.datalen); - // CAUTION: We have to handle the case where the client calls DNSServiceRefDeallocate from within the callback function. - // To do this we set moreptr to point to morebytes. If the client does call DNSServiceRefDeallocate(), - // then that routine will clear morebytes for us, and cause us to exit our loop. - morebytes = more_bytes(sdRef->sockfd); - if (morebytes) - { - cbh.cb_flags |= kDNSServiceFlagsMoreComing; - sdRef->moreptr = &morebytes; - } - if (ptr) sdRef->ProcessReply(sdRef, &cbh, ptr, data + cbh.ipc_hdr.datalen); - // Careful code here: - // If morebytes is non-zero, that means we set sdRef->moreptr above, and the operation was not - // cancelled out from under us, so now we need to clear sdRef->moreptr so we don't leave a stray - // dangling pointer pointing to a long-gone stack variable. - // If morebytes is zero, then one of two thing happened: - // (a) morebytes was 0 above, so we didn't set sdRef->moreptr, so we don't need to clear it - // (b) morebytes was 1 above, and we set sdRef->moreptr, but the operation was cancelled (with DNSServiceRefDeallocate()), - // so we MUST NOT try to dereference our stale sdRef pointer. - if (morebytes) sdRef->moreptr = NULL; - } - free(data); - } while (morebytes); + // CAUTION: We have to handle the case where the client calls DNSServiceRefDeallocate from within the callback function. + // To do this we set moreptr to point to morebytes. If the client does call DNSServiceRefDeallocate(), + // then that routine will clear morebytes for us, and cause us to exit our loop. + morebytes = more_bytes(sdRef->sockfd); + if (morebytes) + { + cbh.cb_flags |= kDNSServiceFlagsMoreComing; + sdRef->moreptr = &morebytes; + } + if (ptr) sdRef->ProcessReply(sdRef, &cbh, ptr, data + cbh.ipc_hdr.datalen); + // Careful code here: + // If morebytes is non-zero, that means we set sdRef->moreptr above, and the operation was not + // cancelled out from under us, so now we need to clear sdRef->moreptr so we don't leave a stray + // dangling pointer pointing to a long-gone stack variable. + // If morebytes is zero, then one of two thing happened: + // (a) morebytes was 0 above, so we didn't set sdRef->moreptr, so we don't need to clear it + // (b) morebytes was 1 above, and we set sdRef->moreptr, but the operation was cancelled (with DNSServiceRefDeallocate()), + // so we MUST NOT try to dereference our stale sdRef pointer. + if (morebytes) sdRef->moreptr = NULL; + } + free(data); + } while (morebytes); - return kDNSServiceErr_NoError; - } + return kDNSServiceErr_NoError; +} void DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdRef) - { - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef"); return; } +{ + if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with NULL DNSServiceRef"); return; } - if (!DNSServiceRefValid(sdRef)) // Also verifies dnssd_SocketValid(sdRef->sockfd) for us too - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); - return; - } + if (!DNSServiceRefValid(sdRef)) // Also verifies dnssd_SocketValid(sdRef->sockfd) for us too + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRefDeallocate called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); + return; + } - // If we're in the middle of a DNSServiceProcessResult() invocation for this DNSServiceRef, clear its morebytes flag to break it out of its while loop - if (sdRef->moreptr) *(sdRef->moreptr) = 0; + // If we're in the middle of a DNSServiceProcessResult() invocation for this DNSServiceRef, clear its morebytes flag to break it out of its while loop + if (sdRef->moreptr) *(sdRef->moreptr) = 0; - if (sdRef->primary) // If this is a subordinate DNSServiceOp, just send a 'stop' command - { - DNSServiceOp **p = &sdRef->primary->next; - while (*p && *p != sdRef) p = &(*p)->next; - if (*p) - { - char *ptr; - size_t len = 0; - ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef); - if (hdr) - { - ConvertHeaderBytes(hdr); - write_all(sdRef->sockfd, (char *)hdr, len); - free(hdr); - } - *p = sdRef->next; - FreeDNSServiceOp(sdRef); - } - } - else // else, make sure to terminate all subordinates as well - { + if (sdRef->primary) // If this is a subordinate DNSServiceOp, just send a 'stop' command + { + DNSServiceOp **p = &sdRef->primary->next; + while (*p && *p != sdRef) p = &(*p)->next; + if (*p) + { + char *ptr; + size_t len = 0; + ipc_msg_hdr *hdr = create_hdr(cancel_request, &len, &ptr, 0, sdRef); + if (hdr) + { + ConvertHeaderBytes(hdr); + write_all(sdRef->sockfd, (char *)hdr, len); + free(hdr); + } + *p = sdRef->next; + FreeDNSServiceOp(sdRef); + } + } + else // else, make sure to terminate all subordinates as well + { #if _DNS_SD_LIBDISPATCH - // The cancel handler will close the fd if a dispatch source has been set - if (sdRef->disp_source) - { - // By setting the ProcessReply to NULL, we make sure that we never call - // the application callbacks ever, after returning from this function. We - // assume that DNSServiceRefDeallocate is called from the serial queue - // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel - // should cancel all the blocks on the queue and hence there should be no more - // callbacks when we return from this function. Setting ProcessReply to NULL - // provides extra protection. - sdRef->ProcessReply = NULL; - dispatch_source_cancel(sdRef->disp_source); - dispatch_release(sdRef->disp_source); - sdRef->disp_source = NULL; - } - // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case, - // when the source was cancelled, the fd was closed in the handler. Currently the source - // is cancelled only when the mDNSResponder daemon dies - else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd); + // The cancel handler will close the fd if a dispatch source has been set + if (sdRef->disp_source) + { + // By setting the ProcessReply to NULL, we make sure that we never call + // the application callbacks ever, after returning from this function. We + // assume that DNSServiceRefDeallocate is called from the serial queue + // that was passed to DNSServiceSetDispatchQueue. Hence, dispatch_source_cancel + // should cancel all the blocks on the queue and hence there should be no more + // callbacks when we return from this function. Setting ProcessReply to NULL + // provides extra protection. + sdRef->ProcessReply = NULL; + shutdown(sdRef->sockfd, SHUT_WR); + dispatch_source_cancel(sdRef->disp_source); + dispatch_release(sdRef->disp_source); + sdRef->disp_source = NULL; + } + // if disp_queue is set, it means it used the DNSServiceSetDispatchQueue API. In that case, + // when the source was cancelled, the fd was closed in the handler. Currently the source + // is cancelled only when the mDNSResponder daemon dies + else if (!sdRef->disp_queue) dnssd_close(sdRef->sockfd); #else - dnssd_close(sdRef->sockfd); + dnssd_close(sdRef->sockfd); #endif - // Free DNSRecords added in DNSRegisterRecord if they have not - // been freed in DNSRemoveRecord - while (sdRef) - { - DNSServiceOp *p = sdRef; - sdRef = sdRef->next; - FreeDNSServiceOp(p); - } - } - } + // Free DNSRecords added in DNSRegisterRecord if they have not + // been freed in DNSRemoveRecord + while (sdRef) + { + DNSServiceOp *p = sdRef; + sdRef = sdRef->next; + // When there is an error reading from the daemon e.g., bad fd, CallbackWithError + // is called which sets moreptr. It might set the moreptr on a subordinate sdRef + // but the application might call DNSServiceRefDeallocate with the main sdRef from + // the callback. Hence, when we loop through the subordinate sdRefs, we need + // to clear the moreptr so that CallbackWithError can terminate itself instead of + // walking through the freed sdRefs. + if (p->moreptr) *(p->moreptr) = 0; + FreeDNSServiceOp(p); + } + } +} DNSServiceErrorType DNSSD_API DNSServiceGetProperty(const char *property, void *result, uint32_t *size) - { - char *ptr; - size_t len = strlen(property) + 1; - ipc_msg_hdr *hdr; - DNSServiceOp *tmp; - uint32_t actualsize; +{ + DNSServiceErrorType err; + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceOp *tmp; + uint32_t actualsize; - DNSServiceErrorType err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL); - if (err) return err; + if (!property || !result || !size) + return kDNSServiceErr_BadParam; - hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp); - if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } + len = strlen(property) + 1; + err = ConnectToServer(&tmp, 0, getproperty_request, NULL, NULL, NULL); + if (err) return err; - put_string(property, &ptr); - err = deliver_request(hdr, tmp); // Will free hdr for us - if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0) - { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } + hdr = create_hdr(getproperty_request, &len, &ptr, 0, tmp); + if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } - actualsize = ntohl(actualsize); - if (read_all(tmp->sockfd, (char*)result, actualsize < *size ? actualsize : *size) < 0) - { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } - DNSServiceRefDeallocate(tmp); + put_string(property, &ptr); + err = deliver_request(hdr, tmp); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(tmp); return err; } - // Swap version result back to local process byte order - if (!strcmp(property, kDNSServiceProperty_DaemonVersion) && *size >= 4) - *(uint32_t*)result = ntohl(*(uint32_t*)result); + if (read_all(tmp->sockfd, (char*)&actualsize, (int)sizeof(actualsize)) < 0) + { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } - *size = actualsize; - return kDNSServiceErr_NoError; - } + actualsize = ntohl(actualsize); + if (read_all(tmp->sockfd, (char*)result, actualsize < *size ? actualsize : *size) < 0) + { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } + DNSServiceRefDeallocate(tmp); + + // Swap version result back to local process byte order + if (!strcmp(property, kDNSServiceProperty_DaemonVersion) && *size >= 4) + *(uint32_t*)result = ntohl(*(uint32_t*)result); + + *size = actualsize; + return kDNSServiceErr_NoError; +} + +DNSServiceErrorType DNSSD_API DNSServiceGetPID(const uint16_t srcport, int32_t *pid) +{ + char *ptr; + ipc_msg_hdr *hdr; + DNSServiceOp *tmp = NULL; + size_t len = sizeof(int32_t); + + DNSServiceErrorType err = ConnectToServer(&tmp, 0, getpid_request, NULL, NULL, NULL); + if (err) return err; + + hdr = create_hdr(getpid_request, &len, &ptr, 0, tmp); + if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } + + put_uint16(srcport, &ptr); + err = deliver_request(hdr, tmp); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(tmp); return err; } + + if (read_all(tmp->sockfd, (char*)pid, sizeof(int32_t)) < 0) + { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_ServiceNotRunning; } + + DNSServiceRefDeallocate(tmp); + return kDNSServiceErr_NoError; +} static void handle_resolve_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *end) - { - char fullname[kDNSServiceMaxDomainName]; - char target[kDNSServiceMaxDomainName]; - uint16_t txtlen; - union { uint16_t s; u_char b[2]; } port; - unsigned char *txtrecord; +{ + char fullname[kDNSServiceMaxDomainName]; + char target[kDNSServiceMaxDomainName]; + uint16_t txtlen; + union { uint16_t s; u_char b[2]; } port; + unsigned char *txtrecord; - get_string(&data, end, fullname, kDNSServiceMaxDomainName); - get_string(&data, end, target, kDNSServiceMaxDomainName); - if (!data || data + 2 > end) goto fail; + get_string(&data, end, fullname, kDNSServiceMaxDomainName); + get_string(&data, end, target, kDNSServiceMaxDomainName); + if (!data || data + 2 > end) goto fail; - port.b[0] = *data++; - port.b[1] = *data++; - txtlen = get_uint16(&data, end); - txtrecord = (unsigned char *)get_rdata(&data, end, txtlen); + port.b[0] = *data++; + port.b[1] = *data++; + txtlen = get_uint16(&data, end); + txtrecord = (unsigned char *)get_rdata(&data, end, txtlen); - if (!data) goto fail; - ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext); - return; - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function + if (!data) goto fail; + ((DNSServiceResolveReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, fullname, target, port.s, txtlen, txtrecord, sdr->AppContext); + return; + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function fail: - syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon"); - } + syslog(LOG_WARNING, "dnssd_clientstub handle_resolve_response: error reading result from daemon"); +} -#if APPLE_OSX_mDNSResponder +#if TARGET_OS_EMBEDDED -static int32_t libSystemVersion = 0; +static int32_t libSystemVersion = 0; -// Return true if the application linked against a version of libsystem where P2P +// Return true if the iOS application linked against a version of libsystem where P2P // interfaces were included by default when using kDNSServiceInterfaceIndexAny. // Using 160.0.0 == 0xa00000 as the version threshold. static int includeP2PWithIndexAny() - { - if (libSystemVersion == 0) - libSystemVersion = NSVersionOfLinkTimeLibrary("System"); +{ + if (libSystemVersion == 0) + libSystemVersion = NSVersionOfLinkTimeLibrary("System"); - if (libSystemVersion < 0xa00000) - return 1; - else - return 0; - } + if (libSystemVersion < 0xa00000) + return 1; + else + return 0; +} -#else // APPLE_OSX_mDNSResponder +#else // TARGET_OS_EMBEDDED -// always return false for non Apple platforms +// always return false for non iOS platforms static int includeP2PWithIndexAny() - { - return 0; - } +{ + return 0; +} -#endif // APPLE_OSX_mDNSResponder +#endif // TARGET_OS_EMBEDDED DNSServiceErrorType DNSSD_API DNSServiceResolve - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - DNSServiceResolveReply callBack, - void *context - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceErrorType err; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *name, + const char *regtype, + const char *domain, + DNSServiceResolveReply callBack, + void *context +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceErrorType err; - if (!name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam; + if (!sdRef || !name || !regtype || !domain || !callBack) return kDNSServiceErr_BadParam; - // Need a real InterfaceID for WakeOnResolve - if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 && - ((interfaceIndex == kDNSServiceInterfaceIndexAny) || - (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) || - (interfaceIndex == kDNSServiceInterfaceIndexUnicast) || - (interfaceIndex == kDNSServiceInterfaceIndexP2P))) - { - return kDNSServiceErr_BadParam; - } - - if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) - flags |= kDNSServiceFlagsIncludeP2P; + // Need a real InterfaceID for WakeOnResolve + if ((flags & kDNSServiceFlagsWakeOnResolve) != 0 && + ((interfaceIndex == kDNSServiceInterfaceIndexAny) || + (interfaceIndex == kDNSServiceInterfaceIndexLocalOnly) || + (interfaceIndex == kDNSServiceInterfaceIndexUnicast) || + (interfaceIndex == kDNSServiceInterfaceIndexP2P) || + (interfaceIndex == kDNSServiceInterfaceIndexBLE))) + { + return kDNSServiceErr_BadParam; + } - err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) + flags |= kDNSServiceFlagsIncludeP2P; - // Calculate total message length - len = sizeof(flags); - len += sizeof(interfaceIndex); - len += strlen(name) + 1; - len += strlen(regtype) + 1; - len += strlen(domain) + 1; + err = ConnectToServer(sdRef, flags, resolve_request, handle_resolve_response, callBack, context); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - hdr = create_hdr(resolve_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + // Calculate total message length + len = sizeof(flags); + len += sizeof(interfaceIndex); + len += strlen(name) + 1; + len += strlen(regtype) + 1; + len += strlen(domain) + 1; - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_string(name, &ptr); - put_string(regtype, &ptr); - put_string(domain, &ptr); + hdr = create_hdr(resolve_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_string(name, &ptr); + put_string(regtype, &ptr); + put_string(domain, &ptr); + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} static void handle_query_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) - { - uint32_t ttl; - char name[kDNSServiceMaxDomainName]; - uint16_t rrtype, rrclass, rdlen; - const char *rdata; +{ + uint32_t ttl; + char name[kDNSServiceMaxDomainName]; + uint16_t rrtype, rrclass, rdlen; + const char *rdata; - get_string(&data, end, name, kDNSServiceMaxDomainName); - rrtype = get_uint16(&data, end); - rrclass = get_uint16(&data, end); - rdlen = get_uint16(&data, end); - rdata = get_rdata(&data, end, rdlen); - ttl = get_uint32(&data, end); + get_string(&data, end, name, kDNSServiceMaxDomainName); + rrtype = get_uint16(&data, end); + rrclass = get_uint16(&data, end); + rdlen = get_uint16(&data, end); + rdata = get_rdata(&data, end, rdlen); + ttl = get_uint32(&data, end); - if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_query_response: error reading result from daemon"); - else ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, name, rrtype, rrclass, rdlen, rdata, ttl, sdr->AppContext); - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function - } + if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_query_response: error reading result from daemon"); + else ((DNSServiceQueryRecordReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, name, rrtype, rrclass, rdlen, rdata, ttl, sdr->AppContext); + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function +} DNSServiceErrorType DNSSD_API DNSServiceQueryRecord - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - uint16_t rrtype, - uint16_t rrclass, - DNSServiceQueryRecordReply callBack, - void *context - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceErrorType err; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *name, + uint16_t rrtype, + uint16_t rrclass, + DNSServiceQueryRecordReply callBack, + void *context +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceErrorType err; - if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) - flags |= kDNSServiceFlagsIncludeP2P; + // NULL name handled below. + if (!sdRef || !callBack) return kDNSServiceErr_BadParam; - err = ConnectToServer(sdRef, flags, query_request, handle_query_response, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) + flags |= kDNSServiceFlagsIncludeP2P; - if (!name) name = "\0"; + err = ConnectToServer(sdRef, flags, query_request, handle_query_response, callBack, context); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - // Calculate total message length - len = sizeof(flags); - len += sizeof(uint32_t); // interfaceIndex - len += strlen(name) + 1; - len += 2 * sizeof(uint16_t); // rrtype, rrclass + if (!name) name = "\0"; - hdr = create_hdr(query_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + // Calculate total message length + len = sizeof(flags); + len += sizeof(uint32_t); // interfaceIndex + len += strlen(name) + 1; + len += 2 * sizeof(uint16_t); // rrtype, rrclass - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_string(name, &ptr); - put_uint16(rrtype, &ptr); - put_uint16(rrclass, &ptr); + hdr = create_hdr(query_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_string(name, &ptr); + put_uint16(rrtype, &ptr); + put_uint16(rrclass, &ptr); + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} static void handle_addrinfo_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) - { - char hostname[kDNSServiceMaxDomainName]; - uint16_t rrtype, rrclass, rdlen; - const char *rdata; - uint32_t ttl; +{ + char hostname[kDNSServiceMaxDomainName]; + uint16_t rrtype, rrclass, rdlen; + const char *rdata; + uint32_t ttl; - get_string(&data, end, hostname, kDNSServiceMaxDomainName); - rrtype = get_uint16(&data, end); - rrclass = get_uint16(&data, end); - rdlen = get_uint16(&data, end); - rdata = get_rdata (&data, end, rdlen); - ttl = get_uint32(&data, end); + get_string(&data, end, hostname, kDNSServiceMaxDomainName); + rrtype = get_uint16(&data, end); + rrclass = get_uint16(&data, end); + rdlen = get_uint16(&data, end); + rdata = get_rdata (&data, end, rdlen); + ttl = get_uint32(&data, end); + (void)rrclass; // Unused - // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for - // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates). - // Other result types, specifically CNAME referrals, are not communicated to the client, because - // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals. - if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon"); - else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA) - { - struct sockaddr_in sa4; - struct sockaddr_in6 sa6; - const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6; - if (rrtype == kDNSServiceType_A) - { - memset(&sa4, 0, sizeof(sa4)); - #ifndef NOT_HAVE_SA_LEN - sa4.sin_len = sizeof(struct sockaddr_in); - #endif - sa4.sin_family = AF_INET; - // sin_port = 0; - if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen); - } - else - { - memset(&sa6, 0, sizeof(sa6)); - #ifndef NOT_HAVE_SA_LEN - sa6.sin6_len = sizeof(struct sockaddr_in6); - #endif - sa6.sin6_family = AF_INET6; - // sin6_port = 0; - // sin6_flowinfo = 0; - // sin6_scope_id = 0; - if (!cbh->cb_err) - { - memcpy(&sa6.sin6_addr, rdata, rdlen); - if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface; - } - } - ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext); - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function - } - } + // We only generate client callbacks for A and AAAA results (including NXDOMAIN results for + // those types, if the client has requested those with the kDNSServiceFlagsReturnIntermediates). + // Other result types, specifically CNAME referrals, are not communicated to the client, because + // the DNSServiceGetAddrInfoReply interface doesn't have any meaningful way to communiate CNAME referrals. + if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_addrinfo_response: error reading result from daemon"); + else if (rrtype == kDNSServiceType_A || rrtype == kDNSServiceType_AAAA) + { + struct sockaddr_in sa4; + struct sockaddr_in6 sa6; + const struct sockaddr *const sa = (rrtype == kDNSServiceType_A) ? (struct sockaddr*)&sa4 : (struct sockaddr*)&sa6; + if (rrtype == kDNSServiceType_A) + { + memset(&sa4, 0, sizeof(sa4)); + #ifndef NOT_HAVE_SA_LEN + sa4.sin_len = sizeof(struct sockaddr_in); + #endif + sa4.sin_family = AF_INET; + // sin_port = 0; + if (!cbh->cb_err) memcpy(&sa4.sin_addr, rdata, rdlen); + } + else + { + memset(&sa6, 0, sizeof(sa6)); + #ifndef NOT_HAVE_SA_LEN + sa6.sin6_len = sizeof(struct sockaddr_in6); + #endif + sa6.sin6_family = AF_INET6; + // sin6_port = 0; + // sin6_flowinfo = 0; + // sin6_scope_id = 0; + if (!cbh->cb_err) + { + memcpy(&sa6.sin6_addr, rdata, rdlen); + if (IN6_IS_ADDR_LINKLOCAL(&sa6.sin6_addr)) sa6.sin6_scope_id = cbh->cb_interface; + } + } + // Validation results are always delivered separately from the actual results of the + // DNSServiceGetAddrInfo. Set the "addr" to NULL as per the documentation. + // + // Note: If we deliver validation results along with the "addr" in the future, we need + // a way to differentiate the negative response from validation-only response as both + // has zero address. + if (!(cbh->cb_flags & kDNSServiceFlagsValidate)) + ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, sa, ttl, sdr->AppContext); + else + ((DNSServiceGetAddrInfoReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, hostname, NULL, 0, sdr->AppContext); + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function + } +} DNSServiceErrorType DNSSD_API DNSServiceGetAddrInfo - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - uint32_t protocol, - const char *hostname, - DNSServiceGetAddrInfoReply callBack, - void *context /* may be NULL */ - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceErrorType err; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + uint32_t protocol, + const char *hostname, + DNSServiceGetAddrInfoReply callBack, + void *context /* may be NULL */ +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceErrorType err; - if (!hostname) return kDNSServiceErr_BadParam; + if (!sdRef || !hostname || !callBack) return kDNSServiceErr_BadParam; - err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + err = ConnectToServer(sdRef, flags, addrinfo_request, handle_addrinfo_response, callBack, context); + if (err) + { + return err; // On error ConnectToServer leaves *sdRef set to NULL + } - // Calculate total message length - len = sizeof(flags); - len += sizeof(uint32_t); // interfaceIndex - len += sizeof(uint32_t); // protocol - len += strlen(hostname) + 1; + // Calculate total message length + len = sizeof(flags); + len += sizeof(uint32_t); // interfaceIndex + len += sizeof(uint32_t); // protocol + len += strlen(hostname) + 1; - hdr = create_hdr(addrinfo_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + hdr = create_hdr(addrinfo_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_uint32(protocol, &ptr); - put_string(hostname, &ptr); + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_uint32(protocol, &ptr); + put_string(hostname, &ptr); + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } - static void handle_browse_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) - { - char replyName[256], replyType[kDNSServiceMaxDomainName], replyDomain[kDNSServiceMaxDomainName]; - get_string(&data, end, replyName, 256); - get_string(&data, end, replyType, kDNSServiceMaxDomainName); - get_string(&data, end, replyDomain, kDNSServiceMaxDomainName); - if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_browse_response: error reading result from daemon"); - else ((DNSServiceBrowseReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, replyName, replyType, replyDomain, sdr->AppContext); - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function - } +{ + char replyName[256], replyType[kDNSServiceMaxDomainName], replyDomain[kDNSServiceMaxDomainName]; + get_string(&data, end, replyName, 256); + get_string(&data, end, replyType, kDNSServiceMaxDomainName); + get_string(&data, end, replyDomain, kDNSServiceMaxDomainName); + if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_browse_response: error reading result from daemon"); + else ((DNSServiceBrowseReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, replyName, replyType, replyDomain, sdr->AppContext); + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function +} DNSServiceErrorType DNSSD_API DNSServiceBrowse - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *regtype, - const char *domain, - DNSServiceBrowseReply callBack, - void *context - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceErrorType err; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *regtype, + const char *domain, + DNSServiceBrowseReply callBack, + void *context +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceErrorType err; - if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) - flags |= kDNSServiceFlagsIncludeP2P; + // NULL domain handled below + if (!sdRef || !regtype || !callBack) return kDNSServiceErr_BadParam; - err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) + flags |= kDNSServiceFlagsIncludeP2P; - if (!domain) domain = ""; - len = sizeof(flags); - len += sizeof(interfaceIndex); - len += strlen(regtype) + 1; - len += strlen(domain) + 1; + err = ConnectToServer(sdRef, flags, browse_request, handle_browse_response, callBack, context); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - hdr = create_hdr(browse_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + if (!domain) domain = ""; + len = sizeof(flags); + len += sizeof(interfaceIndex); + len += strlen(regtype) + 1; + len += strlen(domain) + 1; - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_string(regtype, &ptr); - put_string(domain, &ptr); + hdr = create_hdr(browse_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_string(regtype, &ptr); + put_string(domain, &ptr); + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} -DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain); DNSServiceErrorType DNSSD_API DNSServiceSetDefaultDomainForUser(DNSServiceFlags flags, const char *domain) - { - DNSServiceOp *tmp; - char *ptr; - size_t len = sizeof(flags) + strlen(domain) + 1; - ipc_msg_hdr *hdr; - DNSServiceErrorType err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL); - if (err) return err; +{ + DNSServiceErrorType err; + DNSServiceOp *tmp; + char *ptr; + size_t len; + ipc_msg_hdr *hdr; - hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp); - if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } + if (!domain) return kDNSServiceErr_BadParam; + len = sizeof(flags) + strlen(domain) + 1; - put_flags(flags, &ptr); - put_string(domain, &ptr); - err = deliver_request(hdr, tmp); // Will free hdr for us - DNSServiceRefDeallocate(tmp); - return err; - } + err = ConnectToServer(&tmp, 0, setdomain_request, NULL, NULL, NULL); + if (err) return err; + + hdr = create_hdr(setdomain_request, &len, &ptr, 0, tmp); + if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } + + put_flags(flags, &ptr); + put_string(domain, &ptr); + err = deliver_request(hdr, tmp); // Will free hdr for us + DNSServiceRefDeallocate(tmp); + return err; +} static void handle_regservice_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) - { - char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName]; - get_string(&data, end, name, 256); - get_string(&data, end, regtype, kDNSServiceMaxDomainName); - get_string(&data, end, domain, kDNSServiceMaxDomainName); - if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_regservice_response: error reading result from daemon"); - else ((DNSServiceRegisterReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_err, name, regtype, domain, sdr->AppContext); - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function - } +{ + char name[256], regtype[kDNSServiceMaxDomainName], domain[kDNSServiceMaxDomainName]; + get_string(&data, end, name, 256); + get_string(&data, end, regtype, kDNSServiceMaxDomainName); + get_string(&data, end, domain, kDNSServiceMaxDomainName); + if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_regservice_response: error reading result from daemon"); + else ((DNSServiceRegisterReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_err, name, regtype, domain, sdr->AppContext); + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function +} DNSServiceErrorType DNSSD_API DNSServiceRegister - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *name, - const char *regtype, - const char *domain, - const char *host, - uint16_t PortInNetworkByteOrder, - uint16_t txtLen, - const void *txtRecord, - DNSServiceRegisterReply callBack, - void *context - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceErrorType err; - union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder }; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *name, + const char *regtype, + const char *domain, + const char *host, + uint16_t PortInNetworkByteOrder, + uint16_t txtLen, + const void *txtRecord, + DNSServiceRegisterReply callBack, + void *context +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceErrorType err; + union { uint16_t s; u_char b[2]; } port = { PortInNetworkByteOrder }; - if (!name) name = ""; - if (!regtype) return kDNSServiceErr_BadParam; - if (!domain) domain = ""; - if (!host) host = ""; - if (!txtRecord) txtRecord = (void*)""; + if (!sdRef || !regtype) return kDNSServiceErr_BadParam; + if (!name) name = ""; + if (!domain) domain = ""; + if (!host) host = ""; + if (!txtRecord) txtRecord = (void*)""; - // No callback must have auto-rename - if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam; + // No callback must have auto-rename + if (!callBack && (flags & kDNSServiceFlagsNoAutoRename)) return kDNSServiceErr_BadParam; - if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) - flags |= kDNSServiceFlagsIncludeP2P; + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) + flags |= kDNSServiceFlagsIncludeP2P; - err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + err = ConnectToServer(sdRef, flags, reg_service_request, callBack ? handle_regservice_response : NULL, callBack, context); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - len = sizeof(DNSServiceFlags); - len += sizeof(uint32_t); // interfaceIndex - len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4; - len += 2 * sizeof(uint16_t); // port, txtLen - len += txtLen; + len = sizeof(DNSServiceFlags); + len += sizeof(uint32_t); // interfaceIndex + len += strlen(name) + strlen(regtype) + strlen(domain) + strlen(host) + 4; + len += 2 * sizeof(uint16_t); // port, txtLen + len += txtLen; - hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - if (!callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY; + hdr = create_hdr(reg_service_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + if (!callBack) hdr->ipc_flags |= IPC_FLAGS_NOREPLY; - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_string(name, &ptr); - put_string(regtype, &ptr); - put_string(domain, &ptr); - put_string(host, &ptr); - *ptr++ = port.b[0]; - *ptr++ = port.b[1]; - put_uint16(txtLen, &ptr); - put_rdata(txtLen, txtRecord, &ptr); + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_string(name, &ptr); + put_string(regtype, &ptr); + put_string(domain, &ptr); + put_string(host, &ptr); + *ptr++ = port.b[0]; + *ptr++ = port.b[1]; + put_uint16(txtLen, &ptr); + put_rdata(txtLen, txtRecord, &ptr); - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} static void handle_enumeration_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) - { - char domain[kDNSServiceMaxDomainName]; - get_string(&data, end, domain, kDNSServiceMaxDomainName); - if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_enumeration_response: error reading result from daemon"); - else ((DNSServiceDomainEnumReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, domain, sdr->AppContext); - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function - } +{ + char domain[kDNSServiceMaxDomainName]; + get_string(&data, end, domain, kDNSServiceMaxDomainName); + if (!data) syslog(LOG_WARNING, "dnssd_clientstub handle_enumeration_response: error reading result from daemon"); + else ((DNSServiceDomainEnumReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, domain, sdr->AppContext); + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function +} DNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - DNSServiceDomainEnumReply callBack, - void *context - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceErrorType err; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + DNSServiceDomainEnumReply callBack, + void *context +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceErrorType err; + int f1; + int f2; - int f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0; - int f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0; - if (f1 + f2 != 1) return kDNSServiceErr_BadParam; + if (!sdRef || !callBack) return kDNSServiceErr_BadParam; - err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + f1 = (flags & kDNSServiceFlagsBrowseDomains) != 0; + f2 = (flags & kDNSServiceFlagsRegistrationDomains) != 0; + if (f1 + f2 != 1) return kDNSServiceErr_BadParam; - len = sizeof(DNSServiceFlags); - len += sizeof(uint32_t); + err = ConnectToServer(sdRef, flags, enumeration_request, handle_enumeration_response, callBack, context); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - hdr = create_hdr(enumeration_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + len = sizeof(DNSServiceFlags); + len += sizeof(uint32_t); - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); + hdr = create_hdr(enumeration_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} static void ConnectionResponse(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *const data, const char *const end) - { - DNSRecordRef rref = cbh->ipc_hdr.client_context.context; - (void)data; // Unused +{ + (void)data; // Unused - //printf("ConnectionResponse got %d\n", cbh->ipc_hdr.op); - if (cbh->ipc_hdr.op != reg_record_reply_op) - { - // When using kDNSServiceFlagsShareConnection, need to search the list of associated DNSServiceOps - // to find the one this response is intended for, and then call through to its ProcessReply handler. - // We start with our first subordinate DNSServiceRef -- don't want to accidentally match the parent DNSServiceRef. - DNSServiceOp *op = sdr->next; - while (op && (op->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || op->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1])) - op = op->next; - // Note: We may sometimes not find a matching DNSServiceOp, in the case where the client has - // cancelled the subordinate DNSServiceOp, but there are still messages in the pipeline from the daemon - if (op && op->ProcessReply) op->ProcessReply(op, cbh, data, end); - // WARNING: Don't touch op or sdr after this -- client may have called DNSServiceRefDeallocate - return; - } + //printf("ConnectionResponse got %d\n", cbh->ipc_hdr.op); + if (cbh->ipc_hdr.op != reg_record_reply_op) + { + // When using kDNSServiceFlagsShareConnection, need to search the list of associated DNSServiceOps + // to find the one this response is intended for, and then call through to its ProcessReply handler. + // We start with our first subordinate DNSServiceRef -- don't want to accidentally match the parent DNSServiceRef. + DNSServiceOp *op = sdr->next; + while (op && (op->uid.u32[0] != cbh->ipc_hdr.client_context.u32[0] || op->uid.u32[1] != cbh->ipc_hdr.client_context.u32[1])) + op = op->next; + // Note: We may sometimes not find a matching DNSServiceOp, in the case where the client has + // cancelled the subordinate DNSServiceOp, but there are still messages in the pipeline from the daemon + if (op && op->ProcessReply) op->ProcessReply(op, cbh, data, end); + // WARNING: Don't touch op or sdr after this -- client may have called DNSServiceRefDeallocate + return; + } + else + { + DNSRecordRef rec; + for (rec = sdr->rec; rec; rec = rec->recnext) + { + if (rec->uid.u32[0] == cbh->ipc_hdr.client_context.u32[0] && rec->uid.u32[1] == cbh->ipc_hdr.client_context.u32[1]) + break; + } + // The record might have been freed already and hence not an + // error if the record is not found. + if (!rec) + { + syslog(LOG_INFO, "ConnectionResponse: Record not found"); + return; + } + if (rec->sdr != sdr) + { + syslog(LOG_WARNING, "ConnectionResponse: Record sdr mismatch: rec %p sdr %p", rec->sdr, sdr); + return; + } - if (sdr->op == connection_request) - rref->AppCallback(rref->sdr, rref, cbh->cb_flags, cbh->cb_err, rref->AppContext); - else - { - syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request"); - rref->AppCallback(rref->sdr, rref, 0, kDNSServiceErr_Unknown, rref->AppContext); - } - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function - } + if (sdr->op == connection_request || sdr->op == connection_delegate_request) + { + rec->AppCallback(rec->sdr, rec, cbh->cb_flags, cbh->cb_err, rec->AppContext); + } + else + { + syslog(LOG_WARNING, "dnssd_clientstub ConnectionResponse: sdr->op != connection_request"); + rec->AppCallback(rec->sdr, rec, 0, kDNSServiceErr_Unknown, rec->AppContext); + } + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function + } +} DNSServiceErrorType DNSSD_API DNSServiceCreateConnection(DNSServiceRef *sdRef) - { - char *ptr; - size_t len = 0; - ipc_msg_hdr *hdr; - DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - - hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } +{ + DNSServiceErrorType err; + char *ptr; + size_t len = 0; + ipc_msg_hdr *hdr; - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + if (!sdRef) return kDNSServiceErr_BadParam; + err = ConnectToServer(sdRef, 0, connection_request, ConnectionResponse, NULL, NULL); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + + hdr = create_hdr(connection_request, &len, &ptr, 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} + +#if APPLE_OSX_mDNSResponder && !TARGET_IPHONE_SIMULATOR +DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid) +{ + char *ptr; + size_t len = 0; + ipc_msg_hdr *hdr; + + if (!sdRef) return kDNSServiceErr_BadParam; + DNSServiceErrorType err = ConnectToServer(sdRef, 0, connection_delegate_request, ConnectionResponse, NULL, NULL); + if (err) + { + return err; // On error ConnectToServer leaves *sdRef set to NULL + } + + // Only one of the two options can be set. If pid is zero, uuid is used. + // If both are specified only pid will be used. We send across the pid + // so that the daemon knows what to read from the socket. + + len += sizeof(int32_t); + + hdr = create_hdr(connection_delegate_request, &len, &ptr, 0, *sdRef); + if (!hdr) + { + DNSServiceRefDeallocate(*sdRef); + *sdRef = NULL; + return kDNSServiceErr_NoMemory; + } + + if (pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED, &pid, sizeof(pid)) == -1) + { + syslog(LOG_WARNING, "dnssdclientstub: Could not setsockopt() for PID[%d], no entitlements or process(pid) invalid errno:%d (%s)", pid, errno, strerror(errno)); + // Free the hdr in case we return before calling deliver_request() + if (hdr) + free(hdr); + DNSServiceRefDeallocate(*sdRef); + *sdRef = NULL; + return kDNSServiceErr_NoAuth; + } + + if (!pid && setsockopt((*sdRef)->sockfd, SOL_SOCKET, SO_DELEGATED_UUID, uuid, sizeof(uuid_t)) == -1) + { + syslog(LOG_WARNING, "dnssdclientstub: Could not setsockopt() for UUID, no entitlements or process(uuid) invalid errno:%d (%s) ", errno, strerror(errno)); + // Free the hdr in case we return before calling deliver_request() + if (hdr) + free(hdr); + DNSServiceRefDeallocate(*sdRef); + *sdRef = NULL; + return kDNSServiceErr_NoAuth; + } + + put_uint32(pid, &ptr); + + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) + { + DNSServiceRefDeallocate(*sdRef); + *sdRef = NULL; + } + return err; +} +#elif TARGET_IPHONE_SIMULATOR // This hack is for Simulator platform only +DNSServiceErrorType DNSSD_API DNSServiceCreateDelegateConnection(DNSServiceRef *sdRef, int32_t pid, uuid_t uuid) +{ + (void) pid; + (void) uuid; + return DNSServiceCreateConnection(sdRef); +} +#endif DNSServiceErrorType DNSSD_API DNSServiceRegisterRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata, - uint32_t ttl, - DNSServiceRegisterRecordReply callBack, - void *context - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr = NULL; - DNSRecordRef rref = NULL; - DNSRecord **p; - int f1 = (flags & kDNSServiceFlagsShared) != 0; - int f2 = (flags & kDNSServiceFlagsUnique) != 0; - if (f1 + f2 != 1) return kDNSServiceErr_BadParam; +( + DNSServiceRef sdRef, + DNSRecordRef *RecordRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *fullname, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, + const void *rdata, + uint32_t ttl, + DNSServiceRegisterRecordReply callBack, + void *context +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr = NULL; + DNSRecordRef rref = NULL; + DNSRecord **p; + int f1 = (flags & kDNSServiceFlagsShared) != 0; + int f2 = (flags & kDNSServiceFlagsUnique) != 0; + if (f1 + f2 != 1) return kDNSServiceErr_BadParam; - if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) - flags |= kDNSServiceFlagsIncludeP2P; + if ((interfaceIndex == kDNSServiceInterfaceIndexAny) && includeP2PWithIndexAny()) + flags |= kDNSServiceFlagsIncludeP2P; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!sdRef || !RecordRef || !fullname || (!rdata && rdlen) || !callBack) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with NULL parameter"); + return kDNSServiceErr_BadParam; + } - if (!DNSServiceRefValid(sdRef)) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); - return kDNSServiceErr_BadReference; - } + if (!DNSServiceRefValid(sdRef)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); + return kDNSServiceErr_BadReference; + } - if (sdRef->op != connection_request) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with non-DNSServiceCreateConnection DNSServiceRef %p %d", sdRef, sdRef->op); - return kDNSServiceErr_BadReference; - } + if (sdRef->op != connection_request && sdRef->op != connection_delegate_request) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRegisterRecord called with non-DNSServiceCreateConnection DNSServiceRef %p %d", sdRef, sdRef->op); + return kDNSServiceErr_BadReference; + } - *RecordRef = NULL; + *RecordRef = NULL; - len = sizeof(DNSServiceFlags); - len += 2 * sizeof(uint32_t); // interfaceIndex, ttl - len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen - len += strlen(fullname) + 1; - len += rdlen; + len = sizeof(DNSServiceFlags); + len += 2 * sizeof(uint32_t); // interfaceIndex, ttl + len += 3 * sizeof(uint16_t); // rrtype, rrclass, rdlen + len += strlen(fullname) + 1; + len += rdlen; - hdr = create_hdr(reg_record_request, &len, &ptr, 1, sdRef); - if (!hdr) return kDNSServiceErr_NoMemory; + // Bump up the uid. Normally for shared operations (kDNSServiceFlagsShareConnection), this + // is done in ConnectToServer. For DNSServiceRegisterRecord, ConnectToServer has already + // been called. As multiple DNSServiceRegisterRecords can be multiplexed over a single + // connection, we need a way to demultiplex the response so that the callback corresponding + // to the right DNSServiceRegisterRecord instance can be called. Use the same mechanism that + // is used by kDNSServiceFlagsShareConnection. create_hdr copies the uid value to ipc + // hdr->client_context which will be returned in the ipc response. + if (++sdRef->uid.u32[0] == 0) + ++sdRef->uid.u32[1]; + hdr = create_hdr(reg_record_request, &len, &ptr, 1, sdRef); + if (!hdr) return kDNSServiceErr_NoMemory; - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_string(fullname, &ptr); - put_uint16(rrtype, &ptr); - put_uint16(rrclass, &ptr); - put_uint16(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - put_uint32(ttl, &ptr); + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_string(fullname, &ptr); + put_uint16(rrtype, &ptr); + put_uint16(rrclass, &ptr); + put_uint16(rdlen, &ptr); + put_rdata(rdlen, rdata, &ptr); + put_uint32(ttl, &ptr); - rref = malloc(sizeof(DNSRecord)); - if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; } - rref->AppContext = context; - rref->AppCallback = callBack; - rref->record_index = sdRef->max_index++; - rref->sdr = sdRef; - rref->recnext = NULL; - *RecordRef = rref; - hdr->client_context.context = rref; - hdr->reg_index = rref->record_index; + rref = malloc(sizeof(DNSRecord)); + if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; } + rref->AppContext = context; + rref->AppCallback = callBack; + rref->record_index = sdRef->max_index++; + rref->sdr = sdRef; + rref->recnext = NULL; + *RecordRef = rref; + // Remember the uid that we are sending across so that we can match + // when the response comes back. + rref->uid = sdRef->uid; + hdr->reg_index = rref->record_index; - p = &(sdRef)->rec; - while (*p) p = &(*p)->recnext; - *p = rref; + p = &(sdRef)->rec; + while (*p) p = &(*p)->recnext; + *p = rref; - return deliver_request(hdr, sdRef); // Will free hdr for us - } + return deliver_request(hdr, sdRef); // Will free hdr for us +} // sdRef returned by DNSServiceRegister() DNSServiceErrorType DNSSD_API DNSServiceAddRecord - ( - DNSServiceRef sdRef, - DNSRecordRef *RecordRef, - DNSServiceFlags flags, - uint16_t rrtype, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ) - { - ipc_msg_hdr *hdr; - size_t len = 0; - char *ptr; - DNSRecordRef rref; - DNSRecord **p; +( + DNSServiceRef sdRef, + DNSRecordRef *RecordRef, + DNSServiceFlags flags, + uint16_t rrtype, + uint16_t rdlen, + const void *rdata, + uint32_t ttl +) +{ + ipc_msg_hdr *hdr; + size_t len = 0; + char *ptr; + DNSRecordRef rref; + DNSRecord **p; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } - if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL DNSRecordRef pointer"); return kDNSServiceErr_BadParam; } - if (sdRef->op != reg_service_request) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op); - return kDNSServiceErr_BadReference; - } + if (!sdRef || !RecordRef || (!rdata && rdlen)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with NULL parameter"); + return kDNSServiceErr_BadParam; + } + if (sdRef->op != reg_service_request) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with non-DNSServiceRegister DNSServiceRef %p %d", sdRef, sdRef->op); + return kDNSServiceErr_BadReference; + } - if (!DNSServiceRefValid(sdRef)) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); - return kDNSServiceErr_BadReference; - } + if (!DNSServiceRefValid(sdRef)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceAddRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); + return kDNSServiceErr_BadReference; + } - *RecordRef = NULL; + *RecordRef = NULL; - len += 2 * sizeof(uint16_t); // rrtype, rdlen - len += rdlen; - len += sizeof(uint32_t); - len += sizeof(DNSServiceFlags); + len += 2 * sizeof(uint16_t); // rrtype, rdlen + len += rdlen; + len += sizeof(uint32_t); + len += sizeof(DNSServiceFlags); - hdr = create_hdr(add_record_request, &len, &ptr, 1, sdRef); - if (!hdr) return kDNSServiceErr_NoMemory; - put_flags(flags, &ptr); - put_uint16(rrtype, &ptr); - put_uint16(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - put_uint32(ttl, &ptr); + hdr = create_hdr(add_record_request, &len, &ptr, 1, sdRef); + if (!hdr) return kDNSServiceErr_NoMemory; + put_flags(flags, &ptr); + put_uint16(rrtype, &ptr); + put_uint16(rdlen, &ptr); + put_rdata(rdlen, rdata, &ptr); + put_uint32(ttl, &ptr); - rref = malloc(sizeof(DNSRecord)); - if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; } - rref->AppContext = NULL; - rref->AppCallback = NULL; - rref->record_index = sdRef->max_index++; - rref->sdr = sdRef; - rref->recnext = NULL; - *RecordRef = rref; - hdr->reg_index = rref->record_index; + rref = malloc(sizeof(DNSRecord)); + if (!rref) { free(hdr); return kDNSServiceErr_NoMemory; } + rref->AppContext = NULL; + rref->AppCallback = NULL; + rref->record_index = sdRef->max_index++; + rref->sdr = sdRef; + rref->recnext = NULL; + *RecordRef = rref; + hdr->reg_index = rref->record_index; - p = &(sdRef)->rec; - while (*p) p = &(*p)->recnext; - *p = rref; + p = &(sdRef)->rec; + while (*p) p = &(*p)->recnext; + *p = rref; - return deliver_request(hdr, sdRef); // Will free hdr for us - } + return deliver_request(hdr, sdRef); // Will free hdr for us +} // DNSRecordRef returned by DNSServiceRegisterRecord or DNSServiceAddRecord DNSServiceErrorType DNSSD_API DNSServiceUpdateRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags, - uint16_t rdlen, - const void *rdata, - uint32_t ttl - ) - { - ipc_msg_hdr *hdr; - size_t len = 0; - char *ptr; +( + DNSServiceRef sdRef, + DNSRecordRef RecordRef, + DNSServiceFlags flags, + uint16_t rdlen, + const void *rdata, + uint32_t ttl +) +{ + ipc_msg_hdr *hdr; + size_t len = 0; + char *ptr; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!sdRef || (!rdata && rdlen)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with NULL parameter"); + return kDNSServiceErr_BadParam; + } - if (!DNSServiceRefValid(sdRef)) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); - return kDNSServiceErr_BadReference; - } + if (!DNSServiceRefValid(sdRef)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceUpdateRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); + return kDNSServiceErr_BadReference; + } - // Note: RecordRef is allowed to be NULL + // Note: RecordRef is allowed to be NULL - len += sizeof(uint16_t); - len += rdlen; - len += sizeof(uint32_t); - len += sizeof(DNSServiceFlags); + len += sizeof(uint16_t); + len += rdlen; + len += sizeof(uint32_t); + len += sizeof(DNSServiceFlags); - hdr = create_hdr(update_record_request, &len, &ptr, 1, sdRef); - if (!hdr) return kDNSServiceErr_NoMemory; - hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX; - put_flags(flags, &ptr); - put_uint16(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); - put_uint32(ttl, &ptr); - return deliver_request(hdr, sdRef); // Will free hdr for us - } + hdr = create_hdr(update_record_request, &len, &ptr, 1, sdRef); + if (!hdr) return kDNSServiceErr_NoMemory; + hdr->reg_index = RecordRef ? RecordRef->record_index : TXT_RECORD_INDEX; + put_flags(flags, &ptr); + put_uint16(rdlen, &ptr); + put_rdata(rdlen, rdata, &ptr); + put_uint32(ttl, &ptr); + return deliver_request(hdr, sdRef); // Will free hdr for us +} DNSServiceErrorType DNSSD_API DNSServiceRemoveRecord - ( - DNSServiceRef sdRef, - DNSRecordRef RecordRef, - DNSServiceFlags flags - ) - { - ipc_msg_hdr *hdr; - size_t len = 0; - char *ptr; - DNSServiceErrorType err; +( + DNSServiceRef sdRef, + DNSRecordRef RecordRef, + DNSServiceFlags flags +) +{ + ipc_msg_hdr *hdr; + size_t len = 0; + char *ptr; + DNSServiceErrorType err; - if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } - if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSRecordRef"); return kDNSServiceErr_BadParam; } - if (!sdRef->max_index) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with bad DNSServiceRef"); return kDNSServiceErr_BadReference; } + if (!sdRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSServiceRef"); return kDNSServiceErr_BadParam; } + if (!RecordRef) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with NULL DNSRecordRef"); return kDNSServiceErr_BadParam; } + if (!sdRef->max_index) { syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with bad DNSServiceRef"); return kDNSServiceErr_BadReference; } - if (!DNSServiceRefValid(sdRef)) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); - return kDNSServiceErr_BadReference; - } + if (!DNSServiceRefValid(sdRef)) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceRemoveRecord called with invalid DNSServiceRef %p %08X %08X", sdRef, sdRef->sockfd, sdRef->validator); + return kDNSServiceErr_BadReference; + } - len += sizeof(flags); - hdr = create_hdr(remove_record_request, &len, &ptr, 1, sdRef); - if (!hdr) return kDNSServiceErr_NoMemory; - hdr->reg_index = RecordRef->record_index; - put_flags(flags, &ptr); - err = deliver_request(hdr, sdRef); // Will free hdr for us - if (!err) - { - // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord. - // If so, delink from the list before freeing - DNSRecord **p = &sdRef->rec; - while (*p && *p != RecordRef) p = &(*p)->recnext; - if (*p) *p = RecordRef->recnext; - free(RecordRef); - } - return err; - } + len += sizeof(flags); + hdr = create_hdr(remove_record_request, &len, &ptr, 1, sdRef); + if (!hdr) return kDNSServiceErr_NoMemory; + hdr->reg_index = RecordRef->record_index; + put_flags(flags, &ptr); + err = deliver_request(hdr, sdRef); // Will free hdr for us + if (!err) + { + // This RecordRef could have been allocated in DNSServiceRegisterRecord or DNSServiceAddRecord. + // If so, delink from the list before freeing + DNSRecord **p = &sdRef->rec; + while (*p && *p != RecordRef) p = &(*p)->recnext; + if (*p) *p = RecordRef->recnext; + free(RecordRef); + } + return err; +} DNSServiceErrorType DNSSD_API DNSServiceReconfirmRecord - ( - DNSServiceFlags flags, - uint32_t interfaceIndex, - const char *fullname, - uint16_t rrtype, - uint16_t rrclass, - uint16_t rdlen, - const void *rdata - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - DNSServiceOp *tmp; +( + DNSServiceFlags flags, + uint32_t interfaceIndex, + const char *fullname, + uint16_t rrtype, + uint16_t rrclass, + uint16_t rdlen, + const void *rdata +) +{ + DNSServiceErrorType err; + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + DNSServiceOp *tmp = NULL; - DNSServiceErrorType err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL); - if (err) return err; + if (!fullname || (!rdata && rdlen)) return kDNSServiceErr_BadParam; - len = sizeof(DNSServiceFlags); - len += sizeof(uint32_t); - len += strlen(fullname) + 1; - len += 3 * sizeof(uint16_t); - len += rdlen; - hdr = create_hdr(reconfirm_record_request, &len, &ptr, 0, tmp); - if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } + err = ConnectToServer(&tmp, flags, reconfirm_record_request, NULL, NULL, NULL); + if (err) return err; - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_string(fullname, &ptr); - put_uint16(rrtype, &ptr); - put_uint16(rrclass, &ptr); - put_uint16(rdlen, &ptr); - put_rdata(rdlen, rdata, &ptr); + len = sizeof(DNSServiceFlags); + len += sizeof(uint32_t); + len += strlen(fullname) + 1; + len += 3 * sizeof(uint16_t); + len += rdlen; + hdr = create_hdr(reconfirm_record_request, &len, &ptr, 0, tmp); + if (!hdr) { DNSServiceRefDeallocate(tmp); return kDNSServiceErr_NoMemory; } + + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_string(fullname, &ptr); + put_uint16(rrtype, &ptr); + put_uint16(rrclass, &ptr); + put_uint16(rdlen, &ptr); + put_rdata(rdlen, rdata, &ptr); + + err = deliver_request(hdr, tmp); // Will free hdr for us + DNSServiceRefDeallocate(tmp); + return err; +} - err = deliver_request(hdr, tmp); // Will free hdr for us - DNSServiceRefDeallocate(tmp); - return err; - } static void handle_port_mapping_response(DNSServiceOp *const sdr, const CallbackHeader *const cbh, const char *data, const char *const end) - { - union { uint32_t l; u_char b[4]; } addr; - uint8_t protocol; - union { uint16_t s; u_char b[2]; } internalPort; - union { uint16_t s; u_char b[2]; } externalPort; - uint32_t ttl; +{ + union { uint32_t l; u_char b[4]; } addr; + uint8_t protocol; + union { uint16_t s; u_char b[2]; } internalPort; + union { uint16_t s; u_char b[2]; } externalPort; + uint32_t ttl; - if (!data || data + 13 > end) goto fail; + if (!data || data + 13 > end) goto fail; - addr .b[0] = *data++; - addr .b[1] = *data++; - addr .b[2] = *data++; - addr .b[3] = *data++; - protocol = *data++; - internalPort.b[0] = *data++; - internalPort.b[1] = *data++; - externalPort.b[0] = *data++; - externalPort.b[1] = *data++; - ttl = get_uint32(&data, end); - if (!data) goto fail; + addr.b[0] = *data++; + addr.b[1] = *data++; + addr.b[2] = *data++; + addr.b[3] = *data++; + protocol = *data++; + internalPort.b[0] = *data++; + internalPort.b[1] = *data++; + externalPort.b[0] = *data++; + externalPort.b[1] = *data++; + ttl = get_uint32(&data, end); + if (!data) goto fail; - ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext); - return; - // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function + ((DNSServiceNATPortMappingReply)sdr->AppCallback)(sdr, cbh->cb_flags, cbh->cb_interface, cbh->cb_err, addr.l, protocol, internalPort.s, externalPort.s, ttl, sdr->AppContext); + return; + // MUST NOT touch sdr after invoking AppCallback -- client is allowed to dispose it from within callback function -fail: - syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon"); - } + fail : + syslog(LOG_WARNING, "dnssd_clientstub handle_port_mapping_response: error reading result from daemon"); +} DNSServiceErrorType DNSSD_API DNSServiceNATPortMappingCreate - ( - DNSServiceRef *sdRef, - DNSServiceFlags flags, - uint32_t interfaceIndex, - uint32_t protocol, /* TCP and/or UDP */ - uint16_t internalPortInNetworkByteOrder, - uint16_t externalPortInNetworkByteOrder, - uint32_t ttl, /* time to live in seconds */ - DNSServiceNATPortMappingReply callBack, - void *context /* may be NULL */ - ) - { - char *ptr; - size_t len; - ipc_msg_hdr *hdr; - union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder }; - union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder }; +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + uint32_t interfaceIndex, + uint32_t protocol, /* TCP and/or UDP */ + uint16_t internalPortInNetworkByteOrder, + uint16_t externalPortInNetworkByteOrder, + uint32_t ttl, /* time to live in seconds */ + DNSServiceNATPortMappingReply callBack, + void *context /* may be NULL */ +) +{ + char *ptr; + size_t len; + ipc_msg_hdr *hdr; + union { uint16_t s; u_char b[2]; } internalPort = { internalPortInNetworkByteOrder }; + union { uint16_t s; u_char b[2]; } externalPort = { externalPortInNetworkByteOrder }; - DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, callBack, context); - if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL + DNSServiceErrorType err = ConnectToServer(sdRef, flags, port_mapping_request, handle_port_mapping_response, callBack, context); + if (err) return err; // On error ConnectToServer leaves *sdRef set to NULL - len = sizeof(flags); - len += sizeof(interfaceIndex); - len += sizeof(protocol); - len += sizeof(internalPort); - len += sizeof(externalPort); - len += sizeof(ttl); + len = sizeof(flags); + len += sizeof(interfaceIndex); + len += sizeof(protocol); + len += sizeof(internalPort); + len += sizeof(externalPort); + len += sizeof(ttl); - hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); - if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } + hdr = create_hdr(port_mapping_request, &len, &ptr, (*sdRef)->primary ? 1 : 0, *sdRef); + if (!hdr) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; return kDNSServiceErr_NoMemory; } - put_flags(flags, &ptr); - put_uint32(interfaceIndex, &ptr); - put_uint32(protocol, &ptr); - *ptr++ = internalPort.b[0]; - *ptr++ = internalPort.b[1]; - *ptr++ = externalPort.b[0]; - *ptr++ = externalPort.b[1]; - put_uint32(ttl, &ptr); + put_flags(flags, &ptr); + put_uint32(interfaceIndex, &ptr); + put_uint32(protocol, &ptr); + *ptr++ = internalPort.b[0]; + *ptr++ = internalPort.b[1]; + *ptr++ = externalPort.b[0]; + *ptr++ = externalPort.b[1]; + put_uint32(ttl, &ptr); - err = deliver_request(hdr, *sdRef); // Will free hdr for us - if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } - return err; - } + err = deliver_request(hdr, *sdRef); // Will free hdr for us + if (err) { DNSServiceRefDeallocate(*sdRef); *sdRef = NULL; } + return err; +} #if _DNS_SD_LIBDISPATCH DNSServiceErrorType DNSSD_API DNSServiceSetDispatchQueue - ( - DNSServiceRef service, - dispatch_queue_t queue - ) - { - int dnssd_fd = DNSServiceRefSockFD(service); - if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam; - if (!queue) - { - syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL"); - return kDNSServiceErr_BadParam; - } - if (service->disp_queue) - { - syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already"); - return kDNSServiceErr_BadParam; - } - if (service->disp_source) - { - syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch source set already"); - return kDNSServiceErr_BadParam; - } - service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue); - if (!service->disp_source) - { - syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch_source_create failed"); - return kDNSServiceErr_NoMemory; - } - service->disp_queue = queue; - dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);}); - dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);}); - dispatch_resume(service->disp_source); - return kDNSServiceErr_NoError; - } +( + DNSServiceRef service, + dispatch_queue_t queue +) +{ + int dnssd_fd = DNSServiceRefSockFD(service); + if (dnssd_fd == dnssd_InvalidSocket) return kDNSServiceErr_BadParam; + if (!queue) + { + syslog(LOG_WARNING, "dnssd_clientstub: DNSServiceSetDispatchQueue dispatch queue NULL"); + return kDNSServiceErr_BadParam; + } + if (service->disp_queue) + { + syslog(LOG_WARNING, "dnssd_clientstub DNSServiceSetDispatchQueue dispatch queue set already"); + return kDNSServiceErr_BadParam; + } + if (service->disp_source) + { + syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch source set already"); + return kDNSServiceErr_BadParam; + } + service->disp_source = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, dnssd_fd, 0, queue); + if (!service->disp_source) + { + syslog(LOG_WARNING, "DNSServiceSetDispatchQueue dispatch_source_create failed"); + return kDNSServiceErr_NoMemory; + } + service->disp_queue = queue; + dispatch_source_set_event_handler(service->disp_source, ^{DNSServiceProcessResult(service);}); + dispatch_source_set_cancel_handler(service->disp_source, ^{dnssd_close(dnssd_fd);}); + dispatch_resume(service->disp_source); + return kDNSServiceErr_NoError; +} #endif // _DNS_SD_LIBDISPATCH + +#if !defined(_WIN32) + +static void DNSSD_API SleepKeepaliveCallback(DNSServiceRef sdRef, DNSRecordRef rec, const DNSServiceFlags flags, + DNSServiceErrorType errorCode, void *context) +{ + SleepKAContext *ka = (SleepKAContext *)context; + (void)rec; // Unused + (void)flags; // Unused + + if (sdRef->kacontext != context) + syslog(LOG_WARNING, "SleepKeepaliveCallback context mismatch"); + + if (ka->AppCallback) + ((DNSServiceSleepKeepaliveReply)ka->AppCallback)(sdRef, errorCode, ka->AppContext); +} + +DNSServiceErrorType DNSSD_API DNSServiceSleepKeepalive +( + DNSServiceRef *sdRef, + DNSServiceFlags flags, + int fd, + unsigned int timeout, + DNSServiceSleepKeepaliveReply callBack, + void *context +) +{ + char source_str[INET6_ADDRSTRLEN]; + char target_str[INET6_ADDRSTRLEN]; + struct sockaddr_storage lss; + struct sockaddr_storage rss; + socklen_t len1, len2; + unsigned int len, proxyreclen; + char buf[256]; + DNSServiceErrorType err; + DNSRecordRef record = NULL; + char name[10]; + char recname[128]; + SleepKAContext *ka; + unsigned int i, unique; + + + (void) flags; //unused + if (!timeout) return kDNSServiceErr_BadParam; + + + len1 = sizeof(lss); + if (getsockname(fd, (struct sockaddr *)&lss, &len1) < 0) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive: getsockname %d\n", errno); + return kDNSServiceErr_BadParam; + } + + len2 = sizeof(rss); + if (getpeername(fd, (struct sockaddr *)&rss, &len2) < 0) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive: getpeername %d\n", errno); + return kDNSServiceErr_BadParam; + } + + if (len1 != len2) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive local/remote info not same"); + return kDNSServiceErr_Unknown; + } + + unique = 0; + if (lss.ss_family == AF_INET) + { + struct sockaddr_in *sl = (struct sockaddr_in *)&lss; + struct sockaddr_in *sr = (struct sockaddr_in *)&rss; + unsigned char *ptr = (unsigned char *)&sl->sin_addr; + + if (!inet_ntop(AF_INET, (const void *)&sr->sin_addr, target_str, sizeof (target_str))) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive remote info failed %d", errno); + return kDNSServiceErr_Unknown; + } + if (!inet_ntop(AF_INET, (const void *)&sl->sin_addr, source_str, sizeof (source_str))) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive local info failed %d", errno); + return kDNSServiceErr_Unknown; + } + // Sum of all bytes in the local address and port should result in a unique + // number in the local network + for (i = 0; i < sizeof(struct in_addr); i++) + unique += ptr[i]; + unique += sl->sin_port; + len = snprintf(buf+1, sizeof(buf) - 1, "t=%u h=%s d=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl->sin_port), ntohs(sr->sin_port)); + } + else + { + struct sockaddr_in6 *sl6 = (struct sockaddr_in6 *)&lss; + struct sockaddr_in6 *sr6 = (struct sockaddr_in6 *)&rss; + unsigned char *ptr = (unsigned char *)&sl6->sin6_addr; + + if (!inet_ntop(AF_INET6, (const void *)&sr6->sin6_addr, target_str, sizeof (target_str))) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive remote6 info failed %d", errno); + return kDNSServiceErr_Unknown; + } + if (!inet_ntop(AF_INET6, (const void *)&sl6->sin6_addr, source_str, sizeof (source_str))) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive local6 info failed %d", errno); + return kDNSServiceErr_Unknown; + } + for (i = 0; i < sizeof(struct in6_addr); i++) + unique += ptr[i]; + unique += sl6->sin6_port; + len = snprintf(buf+1, sizeof(buf) - 1, "t=%u H=%s D=%s l=%u r=%u", timeout, source_str, target_str, ntohs(sl6->sin6_port), ntohs(sr6->sin6_port)); + } + + if (len >= (sizeof(buf) - 1)) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit local/remote info"); + return kDNSServiceErr_Unknown; + } + // Include the NULL byte also in the first byte. The total length of the record includes the + // first byte also. + buf[0] = len + 1; + proxyreclen = len + 2; + + len = snprintf(name, sizeof(name), "%u", unique); + if (len >= sizeof(name)) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit unique"); + return kDNSServiceErr_Unknown; + } + + len = snprintf(recname, sizeof(recname), "%s.%s", name, "_keepalive._dns-sd._udp.local"); + if (len >= sizeof(recname)) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive could not fit name"); + return kDNSServiceErr_Unknown; + } + + ka = malloc(sizeof(SleepKAContext)); + if (!ka) return kDNSServiceErr_NoMemory; + ka->AppCallback = callBack; + ka->AppContext = context; + + err = DNSServiceCreateConnection(sdRef); + if (err) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive cannot create connection"); + free(ka); + return err; + } + + // we don't care about the "record". When sdRef gets deallocated later, it will be freed too + err = DNSServiceRegisterRecord(*sdRef, &record, kDNSServiceFlagsUnique, 0, recname, + kDNSServiceType_NULL, kDNSServiceClass_IN, proxyreclen, buf, kDNSServiceInterfaceIndexAny, SleepKeepaliveCallback, ka); + if (err) + { + syslog(LOG_WARNING, "DNSServiceSleepKeepalive cannot create connection"); + free(ka); + return err; + } + (*sdRef)->kacontext = ka; + return kDNSServiceErr_NoError; +} +#endif diff --git a/bonjour-sdk/dnssd_ipc.c b/bonjour-sdk/dnssd_ipc.c index 131510c..0fd7582 100644 --- a/bonjour-sdk/dnssd_ipc.c +++ b/bonjour-sdk/dnssd_ipc.c @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2011 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 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 Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -31,131 +31,131 @@ #if defined(_WIN32) char *win32_strerror(int inErrorCode) - { - static char buffer[1024]; - DWORD n; - memset(buffer, 0, sizeof(buffer)); - n = FormatMessageA( - FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, - (DWORD) inErrorCode, - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - buffer, - sizeof(buffer), - NULL); - if (n > 0) - { - // Remove any trailing CR's or LF's since some messages have them. - while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1])) - buffer[--n] = '\0'; - } - return buffer; - } +{ + static char buffer[1024]; + DWORD n; + memset(buffer, 0, sizeof(buffer)); + n = FormatMessageA( + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + (DWORD) inErrorCode, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + buffer, + sizeof(buffer), + NULL); + if (n > 0) + { + // Remove any trailing CR's or LF's since some messages have them. + while ((n > 0) && isspace(((unsigned char *) buffer)[n - 1])) + buffer[--n] = '\0'; + } + return buffer; +} #endif void put_uint32(const uint32_t l, char **ptr) - { - (*ptr)[0] = (char)((l >> 24) & 0xFF); - (*ptr)[1] = (char)((l >> 16) & 0xFF); - (*ptr)[2] = (char)((l >> 8) & 0xFF); - (*ptr)[3] = (char)((l ) & 0xFF); - *ptr += sizeof(uint32_t); - } +{ + (*ptr)[0] = (char)((l >> 24) & 0xFF); + (*ptr)[1] = (char)((l >> 16) & 0xFF); + (*ptr)[2] = (char)((l >> 8) & 0xFF); + (*ptr)[3] = (char)((l ) & 0xFF); + *ptr += sizeof(uint32_t); +} uint32_t get_uint32(const char **ptr, const char *end) - { - if (!*ptr || *ptr + sizeof(uint32_t) > end) - { - *ptr = NULL; - return(0); - } - else - { - uint8_t *p = (uint8_t*) *ptr; - *ptr += sizeof(uint32_t); - return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3])); - } - } +{ + if (!*ptr || *ptr + sizeof(uint32_t) > end) + { + *ptr = NULL; + return(0); + } + else + { + uint8_t *p = (uint8_t*) *ptr; + *ptr += sizeof(uint32_t); + return((uint32_t) ((uint32_t)p[0] << 24 | (uint32_t)p[1] << 16 | (uint32_t)p[2] << 8 | p[3])); + } +} void put_uint16(uint16_t s, char **ptr) - { - (*ptr)[0] = (char)((s >> 8) & 0xFF); - (*ptr)[1] = (char)((s ) & 0xFF); - *ptr += sizeof(uint16_t); - } +{ + (*ptr)[0] = (char)((s >> 8) & 0xFF); + (*ptr)[1] = (char)((s ) & 0xFF); + *ptr += sizeof(uint16_t); +} uint16_t get_uint16(const char **ptr, const char *end) - { - if (!*ptr || *ptr + sizeof(uint16_t) > end) - { - *ptr = NULL; - return(0); - } - else - { - uint8_t *p = (uint8_t*) *ptr; - *ptr += sizeof(uint16_t); - return((uint16_t) ((uint16_t)p[0] << 8 | p[1])); - } - } +{ + if (!*ptr || *ptr + sizeof(uint16_t) > end) + { + *ptr = NULL; + return(0); + } + else + { + uint8_t *p = (uint8_t*) *ptr; + *ptr += sizeof(uint16_t); + return((uint16_t) ((uint16_t)p[0] << 8 | p[1])); + } +} int put_string(const char *str, char **ptr) - { - if (!str) str = ""; - strcpy(*ptr, str); - *ptr += strlen(str) + 1; - return 0; - } +{ + if (!str) str = ""; + strcpy(*ptr, str); + *ptr += strlen(str) + 1; + return 0; +} int get_string(const char **ptr, const char *const end, char *buffer, int buflen) - { - if (!*ptr) - { - *buffer = 0; - return(-1); - } - else - { - char *lim = buffer + buflen; // Calculate limit - while (*ptr < end && buffer < lim) - { - char c = *buffer++ = *(*ptr)++; - if (c == 0) return(0); // Success - } - if (buffer == lim) buffer--; - *buffer = 0; // Failed, so terminate string, - *ptr = NULL; // clear pointer, - return(-1); // and return failure indication - } - } +{ + if (!*ptr) + { + *buffer = 0; + return(-1); + } + else + { + char *lim = buffer + buflen; // Calculate limit + while (*ptr < end && buffer < lim) + { + char c = *buffer++ = *(*ptr)++; + if (c == 0) return(0); // Success + } + if (buffer == lim) buffer--; + *buffer = 0; // Failed, so terminate string, + *ptr = NULL; // clear pointer, + return(-1); // and return failure indication + } +} void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr) - { - memcpy(*ptr, rdata, rdlen); - *ptr += rdlen; - } +{ + memcpy(*ptr, rdata, rdlen); + *ptr += rdlen; +} const char *get_rdata(const char **ptr, const char *end, int rdlen) - { - if (!*ptr || *ptr + rdlen > end) - { - *ptr = NULL; - return(0); - } - else - { - const char *rd = *ptr; - *ptr += rdlen; - return rd; - } - } +{ + if (!*ptr || *ptr + rdlen > end) + { + *ptr = NULL; + return(0); + } + else + { + const char *rd = *ptr; + *ptr += rdlen; + return rd; + } +} void ConvertHeaderBytes(ipc_msg_hdr *hdr) - { - hdr->version = htonl(hdr->version); - hdr->datalen = htonl(hdr->datalen); - hdr->ipc_flags = htonl(hdr->ipc_flags); - hdr->op = htonl(hdr->op ); - hdr->reg_index = htonl(hdr->reg_index); - } +{ + hdr->version = htonl(hdr->version); + hdr->datalen = htonl(hdr->datalen); + hdr->ipc_flags = htonl(hdr->ipc_flags); + hdr->op = htonl(hdr->op ); + hdr->reg_index = htonl(hdr->reg_index); +} diff --git a/bonjour-sdk/dnssd_ipc.h b/bonjour-sdk/dnssd_ipc.h index 748bbdf..96466a9 100644 --- a/bonjour-sdk/dnssd_ipc.h +++ b/bonjour-sdk/dnssd_ipc.h @@ -1,6 +1,6 @@ /* -*- Mode: C; tab-width: 4 -*- * - * Copyright (c) 2003-2004, Apple Computer, Inc. All rights reserved. + * Copyright (c) 2003-2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -10,7 +10,7 @@ * 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 Apple Computer, Inc. ("Apple") nor the names of its + * 3. Neither the name of Apple Inc. ("Apple") nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * @@ -35,72 +35,72 @@ // Common cross platform services // #if defined(WIN32) -# include -# define dnssd_InvalidSocket INVALID_SOCKET -# define dnssd_SocketValid(s) ((s) != INVALID_SOCKET) -# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK -# define dnssd_EINTR WSAEINTR -# define dnssd_ECONNRESET WSAECONNRESET -# define dnssd_sock_t SOCKET -# define dnssd_socklen_t int -# define dnssd_close(sock) closesocket(sock) -# define dnssd_errno WSAGetLastError() -# define dnssd_strerror(X) win32_strerror(X) -# define ssize_t int -# define getpid _getpid -# define unlink _unlink +# include +# define dnssd_InvalidSocket INVALID_SOCKET +# define dnssd_SocketValid(s) ((s) != INVALID_SOCKET) +# define dnssd_EWOULDBLOCK WSAEWOULDBLOCK +# define dnssd_EINTR WSAEINTR +# define dnssd_ECONNRESET WSAECONNRESET +# define dnssd_socklen_t int +# define dnssd_close(sock) closesocket(sock) +# define dnssd_errno WSAGetLastError() +# define dnssd_strerror(X) win32_strerror(X) +# define ssize_t int +# define getpid _getpid +# define unlink _unlink extern char *win32_strerror(int inErrorCode); #else -# include -# include -# include -# include -# include -# include -# include -# include -# include -# define dnssd_InvalidSocket -1 -# define dnssd_SocketValid(s) ((s) >= 0) -# define dnssd_EWOULDBLOCK EWOULDBLOCK -# define dnssd_EINTR EINTR -# define dnssd_ECONNRESET ECONNRESET -# define dnssd_EPIPE EPIPE -# define dnssd_sock_t int -# define dnssd_socklen_t unsigned int -# define dnssd_close(sock) close(sock) -# define dnssd_errno errno -# define dnssd_strerror(X) strerror(X) +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# define dnssd_InvalidSocket -1 +# define dnssd_SocketValid(s) ((s) >= 0) +# define dnssd_EWOULDBLOCK EWOULDBLOCK +# define dnssd_EINTR EINTR +# define dnssd_ECONNRESET ECONNRESET +# define dnssd_EPIPE EPIPE +# define dnssd_socklen_t unsigned int +# define dnssd_close(sock) close(sock) +# define dnssd_errno errno +# define dnssd_strerror(X) strerror(X) #endif #if defined(USE_TCP_LOOPBACK) -# define AF_DNSSD AF_INET -# define MDNS_TCP_SERVERADDR "127.0.0.1" -# define MDNS_TCP_SERVERPORT 5354 -# define LISTENQ 5 -# define dnssd_sockaddr_t struct sockaddr_in +# define AF_DNSSD AF_INET +# define MDNS_TCP_SERVERADDR "127.0.0.1" +# define MDNS_TCP_SERVERPORT 5354 +# define LISTENQ 5 +# define dnssd_sockaddr_t struct sockaddr_in #else -# define AF_DNSSD AF_LOCAL -# ifndef MDNS_UDS_SERVERPATH -# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" -# endif -# define LISTENQ 100 - // longest legal control path length -# define MAX_CTLPATH 256 -# define dnssd_sockaddr_t struct sockaddr_un +# define AF_DNSSD AF_LOCAL +# ifndef MDNS_UDS_SERVERPATH +# define MDNS_UDS_SERVERPATH "/var/run/mDNSResponder" +# endif +# define MDNS_UDS_SERVERPATH_ENVVAR "DNSSD_UDS_PATH" +# define LISTENQ 100 +// longest legal control path length +# define MAX_CTLPATH (sizeof(((struct sockaddr_un*)0)->sun_path)) +# define dnssd_sockaddr_t struct sockaddr_un #endif // Compatibility workaround #ifndef AF_LOCAL -#define AF_LOCAL AF_UNIX +#define AF_LOCAL AF_UNIX #endif // General UDS constants -#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record +#define TXT_RECORD_INDEX ((uint32_t)(-1)) // record index for default text record // IPC data encoding constants and types #define VERSION 1 -#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client +#define IPC_FLAGS_NOREPLY 1 // set flag if no asynchronous replies are to be sent to client // Structure packing macro. If we're not using GNUC, it's not fatal. Most compilers naturally pack the on-the-wire // structures correctly anyway, so a plain "struct" is usually fine. In the event that structures are not packed @@ -116,10 +116,10 @@ extern char *win32_strerror(int inErrorCode); #endif typedef enum - { - request_op_none = 0, // No request yet received on this connection - connection_request = 1, // connected socket via DNSServiceConnect() - reg_record_request, // reg/remove record only valid for connected sockets +{ + request_op_none = 0, // No request yet received on this connection + connection_request = 1, // connected socket via DNSServiceConnect() + reg_record_request, // reg/remove record only valid for connected sockets remove_record_request, enumeration_request, reg_service_request, @@ -129,55 +129,58 @@ typedef enum reconfirm_record_request, add_record_request, update_record_request, - setdomain_request, // Up to here is in Tiger and B4W 1.0.3 - getproperty_request, // New in B4W 1.0.4 - port_mapping_request, // New in Leopard and B4W 2.0 - addrinfo_request, - send_bpf, // New in SL + setdomain_request, // Up to here is in Tiger and B4W 1.0.3 + getproperty_request, // New in B4W 1.0.4 + port_mapping_request, // New in Leopard and B4W 2.0 + addrinfo_request, + send_bpf, // New in SL + getpid_request, + release_request, + connection_delegate_request, - cancel_request = 63 - } request_op_t; + cancel_request = 63 +} request_op_t; typedef enum - { +{ enumeration_reply_op = 64, reg_service_reply_op, browse_reply_op, resolve_reply_op, query_reply_op, - reg_record_reply_op, // Up to here is in Tiger and B4W 1.0.3 - getproperty_reply_op, // New in B4W 1.0.4 - port_mapping_reply_op, // New in Leopard and B4W 2.0 - addrinfo_reply_op - } reply_op_t; + reg_record_reply_op, // Up to here is in Tiger and B4W 1.0.3 + getproperty_reply_op, // New in B4W 1.0.4 + port_mapping_reply_op, // New in Leopard and B4W 2.0 + addrinfo_reply_op +} reply_op_t; #if defined(_WIN64) -# pragma pack(push,4) +# pragma pack(push,4) #endif // Define context object big enough to hold a 64-bit pointer, // to accomodate 64-bit clients communicating with 32-bit daemon. // There's no reason for the daemon to ever be a 64-bit process, but its clients might be typedef packedunion - { +{ void *context; uint32_t u32[2]; - } client_context_t; +} client_context_t; typedef packedstruct - { +{ uint32_t version; uint32_t datalen; uint32_t ipc_flags; - uint32_t op; // request_op_t or reply_op_t + uint32_t op; // request_op_t or reply_op_t client_context_t client_context; // context passed from client, returned by server in corresponding reply uint32_t reg_index; // identifier for a record registered via DNSServiceRegisterRecord() on a // socket connected by DNSServiceCreateConnection(). Must be unique in the scope of the connection, such that and // index/socket pair uniquely identifies a record. (Used to select records for removal by DNSServiceRemoveRecord()) - } ipc_msg_hdr; +} ipc_msg_hdr; #if defined(_WIN64) -# pragma pack(pop) +# pragma pack(pop) #endif // routines to write to and extract data from message buffers. @@ -202,16 +205,16 @@ int get_string(const char **ptr, const char *const end, char *buffer, int buflen void put_rdata(const int rdlen, const unsigned char *rdata, char **ptr); const char *get_rdata(const char **ptr, const char *end, int rdlen); // return value is rdata pointed to by *ptr - - // rdata is not copied from buffer. +// rdata is not copied from buffer. void ConvertHeaderBytes(ipc_msg_hdr *hdr); struct CompileTimeAssertionChecks_dnssd_ipc - { - // Check that the compiler generated our on-the-wire packet format structure definitions - // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries. - char assert0[(sizeof(client_context_t) == 8) ? 1 : -1]; - char assert1[(sizeof(ipc_msg_hdr) == 28) ? 1 : -1]; - }; +{ + // Check that the compiler generated our on-the-wire packet format structure definitions + // properly packed, without adding padding bytes to align fields on 32-bit or 64-bit boundaries. + char assert0[(sizeof(client_context_t) == 8) ? 1 : -1]; + char assert1[(sizeof(ipc_msg_hdr) == 28) ? 1 : -1]; +}; #endif // DNSSD_IPC_H