/*
 * Copyright © 2009 Apple Inc. All rights reserved.
 *
 * @APPLE_LICENSE_HEADER_START@
 * 
 * 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 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 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * @APPLE_LICENSE_HEADER_END@
 */
#ifndef __NOTIFICATION_H__
#define __NOTIFICATION_H__

#include <sys/cdefs.h>
#include <stdint.h>
#include <mach/message.h>

/*
 * These routines allow processes to exchange stateless notification events.
 *
 * Notifications are associated with names in a namespace shared by all
 * clients of the system.  Clients may post notifications for names, and
 * may monitor names for posted notifications.  Clients may request
 * notification delivery by a number of different methods.
 *
 * Clients desiring to monitor names in the notification system must
 * register with the system, providing a name and other information
 * required for the desired notification delivery method.  Clients are
 * given an integer token representing the registration.
 *
 * Notification delivery is provided on a best-effort basis, but is not
 * reliable.  Limitations in the service may cause some notifications to
 * be dropped, particularly under heavily loaded conditions.
 *
 * Notifications may be coalesced in some cases.  Multiple events posted
 * for a name in rapid succession may result in a single notification sent
 * to clients registered for notification for that name.  Clients checking
 * for changes using the notify_check() routine cannot determine if
 * more than one event pas been posted since a previous call to 
 * notify_check() for that name.
 *
 * "False positives" may occur in notify_check() when used with a token
 * generated by notify_register_check() due to implementation constraints.
 * This behavior may vary in future releases.  
 */

/*
 * Status codes returned by the API.
 */
#define NOTIFY_STATUS_OK 0
#define NOTIFY_STATUS_INVALID_NAME 1
#define NOTIFY_STATUS_INVALID_TOKEN 2
#define NOTIFY_STATUS_INVALID_PORT 3
#define NOTIFY_STATUS_INVALID_FILE 4
#define NOTIFY_STATUS_INVALID_SIGNAL 5
#define NOTIFY_STATUS_INVALID_REQUEST 6
#define NOTIFY_STATUS_NOT_AUTHORIZED 7
#define NOTIFY_STATUS_FAILED 1000000

/*
 * Flag bits used for registration.
 */
#define NOTIFY_REUSE 0x00000001


__BEGIN_DECLS

/* 
 * Post a notification for a name.
 *
 * This is the only call that is required for a notification producer.
 * Returns status.
 */
uint32_t notify_post(const char *name);

/*
 * Creates a registration token be used with notify_check(),
 * but no active notifications will be delivered.
 *
 * Input parameter
 *     name - notification name
 * Output parameter
 *     out_token - registration token
 * Returns status.
 */
uint32_t notify_register_check(const char *name, int *out_token);

/*
 * Request notification delivery by UNIX signal.
 *
 * A client may request signal notification for multiple names.  After a signal
 * is delivered, the notify_check() routine may be called with each notification 
 * token to determine which name (if any) generated the signal notification.
 *
 * Input parameters
 *     name - notification name
 *     sig  - signal number (see signal(3))
 * Output parameter
 *     out_token - notification token
 * Returns status.
 */
uint32_t notify_register_signal(const char *name, int sig, int *out_token);

/*
 * Request notification by mach message.  
 *
 * Notifications are delivered by an empty message sent to a mach port.
 * By default, a new port is allocated and a pointer to it is returned
 * as the value of "notify_port".  A mach port previously returned by a 
 * call to this routine may be used for notifications if a pointer to that
 * port is passed in to the routine and NOTIFY_REUSE is set in the flags
 * parameter.  The notification service must be able to extract send
 * rights to the port.
 *
 * Note that the kernel limits the size of the message queue for any port.
 * If it is important that notifications should not be lost due to queue
 * overflow, clients should service messages quickly, and be careful about
 * using the same port for notifications for more than one name.
 *
 * A notification message has an empty message body.  The msgh_id field
 * in the mach message header will have the value of the notification
 * token.  If a port is reused for multiple notification registrations,
 * the msgh_id value may be used to determine which name generated
 * the notification.
 *
 * Input parameter
 *     name - notification name
 * Output parameter
 *     out_token - notification token
 * Input/Output parameter
 *     notify_port - pointer to a mach port
 * Returns status.
 */
uint32_t notify_register_mach_port(const char *name, mach_port_t *notify_port, int flags, int *out_token);

/*
 * Request notification by a write to a file descriptor. 
 *
 * Notifications are delivered by a write to a file descriptor.
 * By default, a new file descriptor is created and a pointer to it
 * is returned as the value of "notify_fd".  A file descriptor created
 * by a previous call to this routine may be used for notifications if
 * a pointer to that file descriptor is passed in to the routine and
 * NOTIFY_REUSE is set in the flags parameter. 
 *
 * Note that the kernel limits the buffer space for queued writes on a
 * file descriptor.  If it is important that notifications should not be
 * lost due to queue overflow, clients should service messages quickly,
 * and be careful about using the same file descriptor for notifications
 * for more than one name.
 *
 * Notifications are delivered by an integer value written to the
 * file descriptor.  The value will match the notification token
 * for which the notification was generated.
 *
 * Input parameter
 *     name - notification name
 * Output parameter
 *     out_token - notification token
 * Input/Output parameter
 *     notify_fd - pointer to a file descriptor
 * Returns status.
 */
uint32_t notify_register_file_descriptor(const char *name, int *notify_fd, int flags, int *out_token);

/*
 * Check if any notifications have been posted.
 *
 * Output parameter check is set to 0 for false, 1 for true.  Returns status.
 * check is set to true the first time notify_check is called for a token.
 * Subsequent calls set check to true when notifications have been posted for
 * the name associated with the notification token.  This routine is independent
 * of notify_post().  That is, check will be true if an application calls
 * notify_post() for a name and then calls notify_check() for a token associated
 * with that name.
 *
 * Input parameter
 *     token - notification token
 * Output parameter
 *     check - true/false indication
 * Returns status.
 */
uint32_t notify_check(int token, int *check);

/*
 * Cancel notification and free resources associated with a notification
 * token.  Mach ports and file descriptor associated with a token are released 
 * (deallocated or closed) when all registration tokens associated with 
 * the port or file descriptor have been cancelled.
 *
 * Input parameter
 *     token - notification token
 * Returns status.
 */
uint32_t notify_cancel(int token);

__END_DECLS

#endif __NOTIFICATION_H__
