File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / mpd / src / msg.c
Revision 1.1: download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 23:32:47 2012 UTC (12 years, 10 months ago) by misho
CVS tags: MAIN, HEAD
Initial revision


/*
 * msg.c
 *
 * Written by Archie Cobbs <archie@freebsd.org>
 * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
 * See ``COPYRIGHT.whistle''
 */

#include "ppp.h"
#include "msg.h"

/*
 * DEFINITIONS
 */

/* Which pipe file descriptor is which */

  #define PIPE_READ		0
  #define PIPE_WRITE		1

  struct mpmsg
  {
    int		type;
    void	(*func)(int type, void *arg);
    void	*arg;
    const char	*dbg;
  };
  typedef struct mpmsg	*Msg;

  #define	MSG_QUEUE_LEN	8192
  #define	MSG_QUEUE_MASK	0x1FFF

  struct mpmsg	msgqueue[MSG_QUEUE_LEN];
  int		msgqueueh = 0;
  int		msgqueuet = 0;
  #define	QUEUELEN()	((msgqueueh >= msgqueuet)?	\
	(msgqueueh - msgqueuet):(msgqueueh + MSG_QUEUE_LEN - msgqueuet))

  int           msgpipe[2];
  int		msgpipesent = 0;
  EventRef	msgevent;

/*
 * INTERNAL FUNCTIONS
 */

  static void	MsgEvent(int type, void *cookie);

/*
 * MsgRegister()
 */

void
MsgRegister2(MsgHandler *m, void (*func)(int type, void *arg), const char *dbg)
{
    if ((msgpipe[0]==0) || (msgpipe[1]==0)) {
	if (pipe(msgpipe) < 0) {
	    Perror("%s: Can't create message pipe", 
		__FUNCTION__);
	    DoExit(EX_ERRDEAD);
	}
	fcntl(msgpipe[PIPE_READ], F_SETFD, 1);
	fcntl(msgpipe[PIPE_WRITE], F_SETFD, 1);

	if (fcntl(msgpipe[PIPE_READ], F_SETFL, O_NONBLOCK) < 0)
    	    Perror("%s: fcntl", __FUNCTION__);
	if (fcntl(msgpipe[PIPE_WRITE], F_SETFL, O_NONBLOCK) < 0)
    	    Perror("%s: fcntl", __FUNCTION__);

	if (EventRegister(&msgevent, EVENT_READ,
		msgpipe[PIPE_READ], EVENT_RECURRING, MsgEvent, NULL) < 0) {
	    Perror("%s: Can't register event", __FUNCTION__);
	    DoExit(EX_ERRDEAD);
        }
    }

    m->func = func;
    m->dbg = dbg;
}

/*
 * MsgUnRegister()
 */

void
MsgUnRegister(MsgHandler *m)
{
    m->func = NULL;
    m->dbg = NULL;
}

/*
 * MsgEvent()
 */

static void
MsgEvent(int type, void *cookie)
{
    char	buf[16];
    /* flush signaling pipe */
    msgpipesent = 0;
    while (read(msgpipe[PIPE_READ], buf, sizeof(buf)) == sizeof(buf));

    while (msgqueuet != msgqueueh) {
	Log(LG_EVENTS, ("EVENT: Message %d to %s received",
	    msgqueue[msgqueuet].type, msgqueue[msgqueuet].dbg));
	(*(msgqueue[msgqueuet].func))(msgqueue[msgqueuet].type, msgqueue[msgqueuet].arg);
	Log(LG_EVENTS, ("EVENT: Message %d to %s processed",
	    msgqueue[msgqueuet].type, msgqueue[msgqueuet].dbg));

	msgqueuet = (msgqueuet + 1) & MSG_QUEUE_MASK;
	SETOVERLOAD(QUEUELEN());
    }
}

/*
 * MsgSend()
 */

void
MsgSend(MsgHandler *m, int type, void *arg)
{
    assert(m);
    assert(m->func);

    msgqueue[msgqueueh].type = type;
    msgqueue[msgqueueh].func = m->func;
    msgqueue[msgqueueh].arg = arg;
    msgqueue[msgqueueh].dbg = m->dbg;

    msgqueueh = (msgqueueh + 1) & MSG_QUEUE_MASK;
    if (msgqueuet == msgqueueh) {
        Log(LG_ERR, ("%s: Fatal message queue overflow!", __FUNCTION__));
        DoExit(EX_ERRDEAD);
    }

    SETOVERLOAD(QUEUELEN());

    if (!msgpipesent) {
	char	buf[1] = { 0x2a };
	if (write(msgpipe[PIPE_WRITE], buf, 1) > 0)
	    msgpipesent = 1;
    }
    Log(LG_EVENTS, ("EVENT: Message %d to %s sent", type, m->dbg));
}

/*
 * MsgName()
 */

const char *
MsgName(int msg)
{
  switch (msg)
  {
    case MSG_OPEN:
      return("OPEN");
    case MSG_CLOSE:
      return("CLOSE");
    case MSG_UP:
      return("UP");
    case MSG_DOWN:
      return("DOWN");
    case MSG_SHUTDOWN:
      return("SHUTDOWN");
    default:
      return("???");
  }
}


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>