To interact with the discovery network, first you create a session by calling sw_discovery_init.
Then you set up reply functions by calling sw_discovery_publish
, sw_discovery_browse_domains
, sw_discovery_browse
, and/or sw_discovery_resolve
. The reply functions are callbacks that you write, through which your code is notified that new services have become available, an attempt to publish a service succeeded or failed, etc.
Console applications
When writing console applications using Howl, call sw_discovery_run
to yield the CPU to Howl and enable your reply functions to be called as those events occur.
GUI applications
On Windows, Howl has been integrated into the windows message pump, thus there is no need to call sw_discovery_run
. Your callbacks will be invoked using the standard event dispatch routines that Windows provides.
On Mac OS X, Howl has been integrated into CFRunLoop, thus there is no need to call sw_discovery_run
. Your callbacks will be invoked using the standard event dispatch routines that Mac OS X provides.
In other environments (notably X11), Howl has not been integrated into the message loop, so extra work needs to be done to make sure events are dispatched both for UI events and Howl events.
Here are three solutions:
1. Call sw_discovery_socket to return the socket that Howl uses to communicate with mDNSResponder and sw_discovery_read_socket to read data from the socket. This is very useful if it is necessary to integrate Howl with a custom select loop.
2. Put all Howl code into one thread, and have the UI run in another thread.
3. Or, after starting the session with sw_discovery_init
, call sw_discovery_salt
to get the salt object. Call sw_salt_step
to dispatch Howl events. See sw_salt for more information.
sw_result
sw_discovery_init
(
sw_discovery *session)
session
is allocated by the user and filled in by Howl.
The session created by sw_discovery_init
is not thread-safe.
In a session created by sw_discovery_init
, after calling each discovery function that calls a reply function, you must call sw_discovery_run
to yield the CPU in console applications. Only then will the reply functions be called. In Windows and Mac OS X GUI applications, it is not necessary to call sw_discovery_run.
The session will attempt to establish a link to an external mDNSResponder service.
int run_complete_discovery_session(void)
{
sw_discovery session;
if (sw_discovery_init(&session) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
.
. // set up reply functions here
.
sw_discovery_run(session);
}
sw_discovery_fina
, sw_discovery_run
, sw_discovery_salt
sw_result
sw_discovery_init_with_flags
(
sw_discovery * session,
sw_discovery_init_flags flags)
session
is allocated by the user and filled in by Howl.
The session created by sw_discovery_init_with_flags
is not thread-safe.
In a session created by sw_discovery_init_with_flags
, after calling each discovery function that calls a reply function, you must call sw_discovery_run
to yield the CPU in console applications. Only then will the reply functions be called. In Windows and Mac OS X GUI applications, it is not necessary to call sw_discovery_run.
The session will attempt to establish a link to an mDNSResponder service based on the flags passed in. If SW_DISCOVERY_USE_SHARED_SERVICE is specified, Howl attempts to find an mDNSResponder running externally. If that fails, and SW_DISCOVERY_USE_PRIVATE_SERVICE is specified, Howl will start an mDNSResponder thread in the calling application.
int run_complete_discovery_session(void)
{
sw_discovery session;
if (sw_discovery_init_with_flags(&session, SW_DISCOVERY_USE_SHARED_SERVICE | SW_DISCOVERY_USE_PRIVATE_SERVICE) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
.
. // set up reply functions here
.
sw_discovery_run(session);
}
sw_discovery_fina
, sw_discovery_run
, sw_discovery_salt
sw_result
sw_discovery_salt
(
sw_discovery session,
sw_salt * salt)
The session created by sw_discovery_init
is not thread-safe. Depending on the contents of salt
, it can be suitable for use inside a GUI thread.
int run_complete_discovery_session(void)
{
sw_discovery session;
sw_salt salt;
if (sw_discovery_init_(&session) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
if (sw_discovery_salt(session, &salt) != SW_OKAY)
{
fprintf(stderr, "salt failed\n");
return -1;
}
.
. // set up reply functions here
.
while (1)
{
sw_ulong msecs = 500;
sw_salt_step(salt, &msecs);
}
sw_discovery_fina
, sw_discovery_run
sw_result
sw_discovery_fina
(
sw_discovery session)
int run_complete_discovery_session(void)
{
sw_discovery session;
if (sw_discovery_init(&session) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
.
. // session work here
.
sw_discovery_fina(session);
...
}
sw_discovery_init
, sw_discovery_init_with_salt
sw_result
sw_discovery_publish_host
(
sw_discovery session,
sw_uint32 interface_index,
sw_const_string name,
sw_const_string domain,
sw_ipv4_address address,
sw_discovery_publish_reply
reply,
sw_opaque extra,
sw_discovery_oid * oid)
sw_discovery_publish_host
, the host's availability is known to all processes on the discovery network.
session
: The discovery session.
interface_index
: The interface on which to publish. Pass 0 to mean all interfaces
name
: The name of the host to publish. UTF-8 encoded.
domain
: The name of the Zeroconf domain. UTF-8 encoded. Pass a NULL for the default domain, which is ".local".
address: The address of the host.
reply
: A pointer to the reply function. In reply to the publish call, the Howl system service calls the reply function to return the status of the publish operation. A single call to sw_discovery_publish_host
may trigger the reply function to be called multiple times.
extra
: An arbitrary pointer, which Howl passes to the reply function. Howl never uses or dereferences this pointer.
oid
: Identifies the specific call to sw_discovery_publish_host
, enabling other functions, like the reply function, to refer to the present attempt to publish. oid
is allocated by the user and filled in by Howl.
...
sw_ipv4_address address;
sw_discovery_oid oid;
sw_ipv4_address_init_from_name(&address, "192.168.2.13");
if ((result = sw_discovery_publish_host(
session,
0,
"iTunes_Host",
NULL,
address,
my_publish_reply,
NULL,
&oid)) != SW_OKAY)
{
fprintf(stderr, "publish failed: %d\n", result);
return -1;
}
sw_discovery_run(session);
...
sw_discovery_cancel
, sw_discovery_run
, sw_discovery_publish_reply
sw_result
sw_discovery_publish
(
sw_discovery session,
sw_uint32 interface_index,
sw_const_string name,
sw_const_string type,
sw_const_string domain,
sw_const_string host,
sw_port port,
sw_octets text_record,
sw_ulong text_record_len,
sw_discovery_publish_reply
reply,
sw_opaque extra,
sw_discovery_oid * oid)
sw_discovery_publish
, the service's availability is known to all processes on the discovery network.
session
: The discovery session.
interface_index
: The interface on which to publish. Pass 0 for all interfaces.
name
: The name of the service to publish. UTF-8 encoded.
type
: The name of the type of the service, for example "_http._tcp.". UTF-8 encoded. See zeroconf.org and RFC2782 for details on the format of service type names.
domain
: The name of the Zeroconf domain. UTF-8 encoded. Pass a NULL for the default domain, which is ".local".
host: The host name of the service. UTF-8 encoded. Pass a NULL for the default host, which is the machine that is running the app.
port
: The port number of the socket that the service can be contacted on. For example, an FTP server should be published as residing at port 21.
text_record
: An opaque buffer specifying a DNS style text record for this service. See sw_text_record for more information on how to construct a text record. Can be NULL.
text_record_len
: The length of the text record. See sw_text_record for more information on how to construct a text record. If text record is NULL, then this parameter must be 0.
reply
: A pointer to the reply function. In reply to the publish call, the Howl system service calls the reply function to return the status of the publish operation. A single call to sw_discovery_publish
may trigger the reply function to be called multiple times.
extra
: An arbitrary pointer, which Howl passes to the reply function. Howl never uses or dereferences this pointer.
oid
: Identifies the specific call to sw_discovery_publish_host
, enabling other functions, like the reply function, to refer to the present attempt to publish. oid
is allocated by the user and filled in by Howl.
...
sw_discovery_oid oid;
if ((result = sw_discovery_publish(
session,
0,
"My Web Server",
"_http._tcp.",
NULL,
80,
NULL,
0,
my_publish_reply,
NULL,
&oid)) != SW_OKAY)
{
fprintf(stderr, "publish failed: %d\n", result);
return -1;
}
sw_discovery_run(session);
...
sw_discovery_cancel
, sw_discovery_run
, sw_discovery_publish_reply
sw_result
sw_discovery_browse_domains
(
sw_discovery session,
sw_uint32 interface_index,
sw_discovery_browse_reply
reply,
sw_opaque extra,
sw_discovery_oid * oid)
sw_discovery_browse_domains
, the Howl system service calls your reply function once for each known domain on the discovery network, and each time a new domain appears on the network.
To browse discovery services rather than domains, see sw_discovery_browse
.
session
: The discovery session.
reply
: A pointer to the reply function.
extra
: An arbitrary pointer, which Howl passes to the reply function. Howl never uses or dereferences this pointer.
oid
: Identifies the specific call, enabling other functions, like the reply function, to refer to the correct call. oid
is allocated by the user and filled in by Howl.
sw_discovery_oid oid;
if (sw_discovery_browse_domains(
session,
0,
my_browse_reply,
NULL,
&oid) != SW_OKAY)
{
fprintf(stderr, "sw_discovery_browse_domains failed: %d\n", result);
return -1;
}
sw_discovery_run(session);
sw_discovery_cancel
, sw_discovery_browse
, sw_discovery_browse_reply
sw_result
sw_discovery_browse
(
sw_discovery session,
sw_uint32 interface_index,
sw_const_string type,
sw_const_string domain,
sw_discovery_browse_reply
reply,
sw_opaque extra,
sw_discovery_oid * oid)
sw_discovery_browse
, the Howl system service calls your reply function once for each known service of the specified type on the discovery network, and each time a new service appears on the network or an old service disappears.
session
: The discovery session.
interface_index
: The interface on which to browse. Pass 0 to mean all interfaces.
type
: The name of the type of the service, for example "_http._tcp.". UTF-8 encoded. See zeroconf.org and RFC2782 for details on the format of service type names. A NULL value is not allowed.
domain
: The domain that the service must be available from. UTF-8 encoded. Pass a NULL to allow services from any domain.
reply
: A pointer to the reply function.
extra
: An arbitrary pointer, which Howl passes to the reply function. Howl never uses or dereferences this pointer.
oid
: Identifies the specific call, enabling other functions, like the reply function, to refer to the correct call. oid
is allocated by the user and filled in by Howl.
sw_discovery_oid oid;
if ((result = sw_discovery_browse(
session,
0,
"_ftp._tcp.",
NULL,
my_browse_reply,
NULL,
&oid)) != SW_OKAY)
{
fprintf(stderr, "sw_discovery_browse failed: %d\n", result);
return -1;
}
sw_discovery_run(session);
sw_discovery_cancel
sw_result
sw_discovery_resolve
(
sw_discovery session,
sw_uint32 interface_index,
sw_const_string name,
sw_const_string type,
sw_const_string domain,
sw_discovery_resolve_reply
reply,
sw_opaque extra,
sw_discovery_oid * oid)
sw_discovery_resolve
and each time the port number or IP address changes.
session
: The discovery session.
interface_index
: The interface on which to resolve. Pass 0 for all interfaces.
name
: The name of the service to resolve. UTF-8 encoded.
type
: The name of the type of the service, for example "_http._tcp.". UTF-8 encoded. See zeroconf.org and RFC2782 for details on the format of service type names. A NULL value is not allowed.
domain
: The domain that the service must be available from. UTF-8 encoded. Pass a NULL to allow services from any domain.
reply
: A pointer to the reply function.
extra
: An arbitrary pointer, which Howl passes to the reply function. Howl never uses or dereferences this pointer.
oid
: Identifies the specific call, enabling other functions, like the reply function, to refer to the correct call. oid
is allocated by the user and filled in by Howl.
sw_discovery_browse
:
.
.
.
sw_result err;
sw_discovery_oid oid;
switch (status)
{
.
.
.
case SW_DISCOVERY_BROWSE_ADD_SERVICE:
{
result = sw_discovery_resolve(
session,
0,
name,
type,
domain,
my_resolver,
NULL,
&oid);
}
break;
.
.
.
}
Note that there is no call to sw_discovery_run
, because sw_discovery_resolve
was called inside a reply function. Control of the CPU will return to Howl when the reply function returns.
sw_discovery_cancel
sw_result
sw_discovery_query_record
(
sw_discovery session,
sw_uint32 interface_index,
sw_uint32 flags,
sw_const_string fullname,
sw_uint16 rrtype,
sw_uint16 rrclass,
sw_discovery_query_record_reply
reply,
sw_opaque extra,
sw_discovery_oid * oid)
session
: The discovery session.
interface_index
: The interface on which to query. Pass 0 for all interfaces.
fullname
: The fullname of the service to resolve. UTF-8 encoded.
rrtype
: The resource record type of the record to query.
rrclass
: The resource record class of the record to query.
reply
: A pointer to the reply function.
extra
: An arbitrary pointer, which Howl passes to the reply function. Howl never uses or dereferences this pointer.
oid
: Identifies the specific call, enabling other functions, like the reply function, to refer to the correct call. oid
is allocated by the user and filled in by Howl.
.
.
sw_result err;
sw_discovery_oid oid;
result = sw_discovery_resolve(
session,
0,
"blob.local.",
1,
1,
my_query,
NULL,
&oid);
.
.
sw_discovery_cancel
sw_result
sw_discovery_cancel
(
sw_discovery session,
sw_discovery_oid oid)
session
: The discovery session.
oid
: Identifies the specific call.
if (sw_discovery_cancel(session, oid) != SW_OKAY)
{
fprintf(stderr, "cancel failed\n");
return -1;
}
sw_discovery_run
sw_result
sw_discovery_run
(sw_discovery session)
Once your program has called sw_discovery_run
, Howl calls reply functions. Before you've called sw_discovery_run
, Howl does not control the CPU and thus cannot call reply functions in response to asynchronous events like new discovery services appearing.
int set_up_discovery_replies(void)
{
sw_discovery session;
if (sw_discovery_init(&session) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
.
. // set up reply functions here
.
sw_discovery_run(session);
}
sw_discovery_stop_run
int
sw_discovery_socket
(sw_discovery session)
int set_up_discovery(void)
{
sw_discovery session;
int socket;
if (sw_discovery_init(&session) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
.
. // set up event handling
.
socket = sw_discovery_socket(session);
}
sw_result
sw_discovery_read_socket
(sw_discovery session)
This call is non-blocking. It will potentially invoke any callbacks that have been registered with the discovery session.
int set_up_discovery(void)
{
sw_discovery session;
if (sw_discovery_init(&session) != SW_OKAY)
{
fprintf(stderr, "init failed\n");
return -1;
}
.
. // set up event handling
.
sw_discovery_read_socket(session);
}
typedef sw_result
(*sw_discovery_publish_reply
)(
sw_discovery discovery,
sw_discovery_oid oid,
sw_discovery_publish_status
status,
sw_opaque extra);
sw_discovery_publish_reply
is the signature of the function called by the Howl system service to indicate the results of an attempt to publish. Howl is told to call this function through a call to sw_discovery_publish
.
handler
: The arbitrary pointer that was passed to sw_discovery_publish
.
discovery
: The discovery session.
status
: The result of the attempt to publish.
oid
: The oid generated by sw_discovery_publish
, identifying the attempt to publish.
extra
: The arbitrary pointer that was passed to sw_discovery_publish
.
sw_discovery_publish_reply
should return the value SW_OKAY. The return value is included to allow future versions to return different values without breaking compatibility with old code.
sw_discovery_publish
typedef sw_result
(*sw_discovery_browse_reply
)(
sw_discovery discovery,
sw_discovery_oid oid,
sw_discovery_browse_status
status,
sw_uint32 interface_index,
sw_const_string name,
sw_const_string type,
sw_const_string domain,
sw_opaque extra);
sw_discovery_browse_reply
is the signature of the function called by the Howl system service to indicate that a discovery domain or service has become available, is no longer available, or to communicate other status information. Howl is told to call this function through a call to sw_discovery_browse_domains
or sw_discovery_browse
.
When a sw_discovery_browse_reply
function is called to report on a service, the name
, type
, and domain
uniquely identify the service.
discovery
: The discovery session.
oid
: The oid generated by sw_discovery_browse_domains
or sw_discovery_browse
, identifying the request to browse.
status
: Info about a domain or service, or status info about the request to browse.
interface_index
: The interface index upon which the browse took place.
name
: The name of the service being reported on by the Howl system service. Undefined for inappropriate values of status
. UTF-8 encoded.
type
: The type of the service being reported on by the Howl system service. UTF-8 encoded. Undefined for inappropriate values of status
.
domain
: The domain being reported on by the Howl system service. UTF-8 encoded. Undefined for inappropriate values of status
.
extra
: The arbitrary pointer that was passed to sw_discovery_browse_domains
or sw_discovery_browse
.
sw_discovery_browse_reply
should return the value SW_OKAY. The return value is included to allow future versions to return different values without breaking compatibility with old code.
sw_discovery_browse_domains
, sw_discovery_browse
typedef sw_result
(*sw_discovery_resolve_reply
)(
sw_discovery discovery,
sw_discovery_oid oid,
sw_uint32 interface_index,
sw_const_string name,
sw_const_string type,
sw_const_string domain,
sw_ipv4_address address,
sw_port port,
sw_octets text_record,
sw_ulong text_record_len,
sw_opaque extra);
sw_discovery_resolve_reply
is the signature of the function called by the Howl system service to communicate the port number and IP address of the socket providing a service. Howl is told to call this function through a call to sw_discovery_resolve
.
discovery
: The discovery session.
oid
: The oid generated by sw_discovery_resolve
, identifying the request to browse.
interface_index
: The interface on which the resolve took place.
name
: The name of the service being reported on by the Howl system service. UTF-8 encoded.
type
: The type of the service being reported on by the Howl system service. UTF-8 encoded.
domain
: The domain being reported on by the Howl system service. UTF-8 encoded.
address
: The IP address of the service.
port
: The port number of the socket where the service is available.
text_record
: A pointer to the raw text record. See sw_text_record_iterator for more information on how to parse this data.
text_record_len
: The length of the text record. See sw_text_record_iterator for more information on how to parse this data.
extra
: The arbitrary pointer that was passed to sw_discovery_resolve
.
sw_discovery_resolve_reply
should return the value SW_OKAY. The return value is included to allow future versions to return different values without breaking compatibility with old code.
sw_discovery_resolve
, sw_ipv4_address
typedef sw_result
(*sw_discovery_query_record_reply
)(
sw_discovery discovery,
sw_discovery_oid oid,
sw_discovery_query_record_status status,
sw_uint32 interface_index,
sw_const_string fullname,
sw_uint16 rrtype,
sw_uint16 rrclass,
sw_uint16 rrdatalen,
sw_const_octets rrdata,
sw_uint32 ttl,
sw_opaque extra);
sw_discovery_resolve_reply
is the signature of the function called by the Howl system service to communicate the port number and IP address of the socket providing a service. Howl is told to call this function through a call to sw_discovery_resolve
.
discovery
: The discovery session.
oid
: The oid generated by sw_discovery_resolve
, identifying the request to browse.
interface_index
: The interface on which the query took place.
fullname
: The fullname of the element being queried.
rrtype
: The type of the resource record being queried.
rrclass
: The class of the resource record being queried.
rrdatalen
: The length of the resource record data
rrdata
: The data associated with the query
ttl
: The ttl associated with this resource record
extra
: The arbitrary pointer that was passed to sw_discovery_resolve
.
sw_discovery_query_record_reply
should return the value SW_OKAY. The return value is included to allow future versions to return different values without breaking compatibility with old code.
sw_discovery_query_record
typedef enum _sw_discovery_init_flags
{ SW_DISCOVERY_USE_SHARED_SERVICE, SW_DISCOVERY_USE_PRIVATE_SERVICE, SW_DISCOVERY_SKIP_VERSION_CHECK }sw_discovery_init_flags
;
sw_discovery_init_with_flags
function.
SW_DISCOVERY_USE_SHARED_SERVICE:
attempt to find an external mDNSResponder service
SW_DISCOVERY_USE_PRIVATE_SERVICE
: attempt to start mDNSResponder in a thread in the calling application.
SW_DISCOVERY_SKIP_VERSION_CHECK
: do not attempt to verify that the client is the proper version with respect to the mDNSResponder service.
Future versions of Howl may add more values.
sw_discovery_init_with_flags
typedef enum sw_discovery_publish_status
{
SW_DISCOVERY_PUBLISH_STARTED,
SW_DISCOVERY_PUBLISH_STOPPED,
SW_DISCOVERY_PUBLISH_NAME_COLLISION,
SW_DISCOVERY_PUBLISH_INVALID
} sw_discovery_publish_status
;
sw_discovery_publish_reply
function.
SW_DISCOVERY_PUBLISH_STARTED
: publishing of the specified service has started successfully.
SW_DISCOVERY_PUBLISH_STOPPED
: the specified service is now no longer published.
SW_DISCOVERY_PUBLISH_NAME_COLLISION
: the specified service could not be published because it has the same name as another service already on the discovery network.
SW_DISCOVERY_PUBLISH_INVALID
: a general catch-all error code.
Future versions of Howl may add more values.
sw_discovery_publish_reply
typedef enum sw_discovery_browse_status
{
SW_DISCOVERY_BROWSE_INVALID,
SW_DISCOVERY_BROWSE_RELEASE,
SW_DISCOVERY_BROWSE_ADD_DOMAIN,
SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN,
SW_DISCOVERY_BROWSE_REMOVE_DOMAIN,
SW_DISCOVERY_BROWSE_ADD_SERVICE,
SW_DISCOVERY_BROWSE_REMOVE_SERVICE
} sw_discovery_browse_status
;
sw_discovery_browse_reply
function.
SW_DISCOVERY_BROWSE_INVALID
: a general catch-all error code.
SW_DISCOVERY_BROWSE_ADD_DOMAIN
: the specified domain is now accessible on the discovery network.
SW_DISCOVERY_BROWSE_ADD_DEFAULT_DOMAIN
: the default discovery domain, "local.", has been established.
SW_DISCOVERY_BROWSE_REMOVE_DOMAIN
: the specified domain has been removed from the discovery network.
SW_DISCOVERY_BROWSE_ADD_SERVICE
: the specified service is now available on the discovery network.
SW_DISCOVERY_BROWSE_REMOVE_SERVICE
: the specified service has been removed from the discovery network.
Future versions of Howl may add more values.
sw_discovery_publish_reply
typedef sw_long sw_result
;
Possible values:
SW_OKAY
: the call succeeded.
SW_DISCOVERY_E_NO_MEM
: failed: out of memory.
SW_DISCOVERY_E_BAD_PARAM
: the function was passed an invalid argument, like attempting to publish a service with an invalid name.
SW_DISCOVERY_E_UNKNOWN
: a general catchall error code.
Future versions of Howl may add more values.