6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER START
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * The contents of this file are subject to the terms of the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Common Development and Distribution License (the "License").
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You may not use this file except in compliance with the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * or http://www.opensolaris.org/os/licensing.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * See the License for the specific language governing permissions
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and limitations under the License.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * When distributing Covered Code, include this CDDL HEADER in each
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If applicable, add the following below this CDDL HEADER, with the
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * fields enclosed by brackets "[]" replaced with your own identifying
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * information: Portions Copyright [yyyy] [name of copyright owner]
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * CDDL HEADER END
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Use is subject to license terms.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <assert.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <dirent.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <errno.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <fcntl.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <pthread.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdio.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <stdlib.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <strings.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <string.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <syslog.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/msg.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/stat.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <sys/types.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <unistd.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include "libnwam_impl.h"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libnwam_priv.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#include <libnwam.h>
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Implementation of event notification mechanism used by the GUI and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * nwamadm. Clients register for events via nwam_events_init() and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * unregister via nwam_events_fini(). nwamd sends events via nwam_event_send()
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * and applications block waiting for a new event to be delivered in
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * nwam_event_wait(). Events are implemented as System V message queues,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * one per event client. The event mechanism has to be resilient to
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * nwamd restarts so that clients do not lose the event connection.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NWAM_EVENT_MSG_DIR "/etc/svc/volatile/nwam/"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NWAM_EVENT_MSG_FILE "nwam_event_msgs"
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NWAM_EVENT_MSG_FILE_PREFIX NWAM_EVENT_MSG_DIR NWAM_EVENT_MSG_FILE
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NWAM_EVENT_MAX_SIZE (sizeof (struct nwam_event) + \
69b43529e65fb6eb0c88e6b7b42025e9bf025b8aMichael Hunter (NWAMD_MAX_NUM_WLANS * sizeof (nwam_wlan_t)))
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NWAM_EVENT_WAIT_TIME 10
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey#define NWAM_EVENT_MAX_NUM_PENDING 25
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This is protecting simultaneous access to the msqid and its configuration.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic pthread_mutex_t event_mutex = PTHREAD_MUTEX_INITIALIZER;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic int event_msqid = -1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeystatic nwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_alloc(nwam_event_t *eventp)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(eventp != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey *eventp = calloc(1, NWAM_EVENT_MAX_SIZE);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (*eventp == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_NO_MEMORY);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_free(nwam_event_t event)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (event != NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey free(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Get next event in queue.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_wait(nwam_event_t *eventp)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_t event;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey assert(eventp != NULL);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_event_alloc(&event)) != NWAM_SUCCESS)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (err);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey while (msgrcv(event_msqid, (struct msgbuf *)event, NWAM_EVENT_MAX_SIZE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey 0, 0) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey switch (errno) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case EAGAIN:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey case EBUSY:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * We see this errno eventhough it isn't
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * documented. Try again. If this causes
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * a busy loop then grab a trace otherwise
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * it's a brace 'til we can figure out why it
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * happens.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey default:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_free(event);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (nwam_errno_to_nwam_error(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Resize event down from maximum size */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((*eventp = realloc(event, event->nwe_size)) == NULL)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_NO_MEMORY);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Register for receipt of events from nwamd. Event delivery is
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * done via a System V message queue.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_events_init(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char eventmsgfile[MAXPATHLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t rc = NWAM_SUCCESS;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey key_t key;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(eventmsgfile, sizeof (eventmsgfile), "%s.%d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_EVENT_MSG_FILE_PREFIX, getpid());
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_lock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (event_msqid != -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = NWAM_ENTITY_IN_USE;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((err = nwam_request_register_unregister
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (NWAM_REQUEST_TYPE_EVENT_REGISTER, eventmsgfile)) != NWAM_SUCCESS) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = err;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((key = ftok(eventmsgfile, 0)) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = nwam_errno_to_nwam_error(errno);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Get system-wide message queue ID */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((event_msqid = msgget(key, 0444)) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey rc = nwam_errno_to_nwam_error(errno);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey goto exit;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyexit:
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (rc);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Un-register for receipt of events from nwamd. Make a request to nwamd
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * to destroy the message queue.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_events_fini(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char eventmsgfile[MAXPATHLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(eventmsgfile, sizeof (eventmsgfile), "%s.%d",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_EVENT_MSG_FILE_PREFIX, getpid());
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_lock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) nwam_request_register_unregister
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (NWAM_REQUEST_TYPE_EVENT_UNREGISTER, eventmsgfile);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey event_msqid = -1;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Create an event queue. Called by nwamd to create System V message queues
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * for clients to listen for events.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_queue_init(const char *eventmsgfile)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int fd;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey key_t key;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((fd = open(eventmsgfile, O_RDWR | O_CREAT | O_TRUNC, 0644)) == -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (nwam_errno_to_nwam_error(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) close(fd);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((key = ftok(eventmsgfile, 0)) == -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (nwam_errno_to_nwam_error(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (msgget(key, 0644 | IPC_CREAT) == -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (nwam_errno_to_nwam_error(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (NWAM_SUCCESS);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Send event to registered listeners via the set of registered System V
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * message queues.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_error_t
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_send(nwam_event_t event)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DIR *dirp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct dirent *dp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct msqid_ds buf;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey key_t key;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int msqid;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char eventmsgfile[MAXPATHLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_error_t err = NWAM_SUCCESS;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((dirp = opendir(NWAM_EVENT_MSG_DIR)) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (nwam_errno_to_nwam_error(errno));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * For each file matching our event message queue file prefix,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * check the queue is still being read, and if so send the message.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey while ((dp = readdir(dirp)) != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strncmp(dp->d_name, NWAM_EVENT_MSG_FILE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strlen(NWAM_EVENT_MSG_FILE)) != 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(eventmsgfile, sizeof (eventmsgfile), "%s/%s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_EVENT_MSG_DIR, dp->d_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((key = ftok(eventmsgfile, 0)) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int errno_save = errno;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey syslog(LOG_INFO, "nwam_event_send: ftok: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strerror(errno_save));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey err = nwam_errno_to_nwam_error(errno_save);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((msqid = msgget(key, 0644)) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int errno_save = errno;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey syslog(LOG_INFO, "nwam_event_send: msgget: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strerror(errno_save));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey err = nwam_errno_to_nwam_error(errno_save);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /* Retrieve stats to analyse queue activity */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (msgctl(msqid, IPC_STAT, &buf) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int errno_save = errno;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey syslog(LOG_INFO, "nwam_event_send: msgctl: %s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strerror(errno_save));
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey err = nwam_errno_to_nwam_error(errno_save);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * If buf.msg_qnum > NWAM_EVENT_MAX_NUM_PENDING
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * _and_ msg_stime is more than 10s after msg_rtime -
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * indicating message(s) have been hanging around unclaimed -
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * we destroy the queue as the client has most likely gone
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * away. This can happen if a registered client hits Ctrl^C.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (buf.msg_qnum > NWAM_EVENT_MAX_NUM_PENDING &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey ((buf.msg_stime + NWAM_EVENT_WAIT_TIME) > buf.msg_rtime)) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_queue_fini(eventmsgfile);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * This shouldn't ever block. If it does then log an error and
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * clean up the queue.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (msgsnd(msqid, (struct msgbuf *)event, event->nwe_size,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey IPC_NOWAIT) == -1) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int errno_save = errno;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey syslog(LOG_ERR, "nwam_event_send: msgsnd: %s, "
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey "destroying message queue %s", strerror(errno_save),
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey eventmsgfile);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_queue_fini(eventmsgfile);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey err = nwam_errno_to_nwam_error(errno_save);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) closedir(dirp);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return (err);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Destroy an event queue. Called by nwamd to destroy the associated message
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * queue.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_queue_fini(const char *eventmsgfile)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey key_t key;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey int msqid;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((key = ftok(eventmsgfile, 0)) != -1 &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (msqid = msgget(key, 0644)) != -1 &&
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey msgctl(msqid, IPC_RMID, NULL) != -1)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) unlink(eventmsgfile);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey/*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * Stop sending events. Called by nwamd to destroy each System V message queue
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * registered.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeyvoid
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskeynwam_event_send_fini(void)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey{
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey DIR *dirp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey struct dirent *dp;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey char eventmsgfile[MAXPATHLEN];
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_lock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if ((dirp = opendir(NWAM_EVENT_MSG_DIR)) == NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey return;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey /*
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * For each file matching our event message queue file prefix,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey * destroy the queue and message file.
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey */
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey while ((dp = readdir(dirp)) != NULL) {
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey if (strncmp(dp->d_name, NWAM_EVENT_MSG_FILE,
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey strlen(NWAM_EVENT_MSG_FILE)) != 0)
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey continue;
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) snprintf(eventmsgfile, sizeof (eventmsgfile), "%s/%s",
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey NWAM_EVENT_MSG_DIR, dp->d_name);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey nwam_event_queue_fini(eventmsgfile);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey }
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey (void) pthread_mutex_unlock(&event_mutex);
6ba597c56d749c61b4f783157f63196d7b2445f0Anurag S. Maskey}