/* sockwatch.c
 *
 * Generic interface functions for Dickon's socket watcher module
 *
 * (C) Joseph Heenan, 1998.
 * All rights reserved.
 *
 * $Id: sockwatch,v 1.3 2000/03/19 12:09:55 joseph Exp $
 *
 */

#include "wimpclib.h"
#include "wimplib.h"
#include "swis.h"

#include "defines.h"

#include "log.h"
#include "sockwatch.h"

int *socketwatch_pollword = 0;

#ifndef FEATURE_MSGRUTILS

#define SWI_SocketWatch_Register      0x52280
#define SWI_SocketWatch_Deregister    0x52281
#define SWI_SocketWatch_AtomicReset   0x52282
#define SWI_SocketWatch_AllocPW       0x52283
#define SWI_SocketWatch_DeallocPW     0x52284

void socketwatch_register( int socket )
{
  const unsigned int bitmask = 1;
  if ( socketwatch_pollword )
    E_CHECK( _swix( SWI_SocketWatch_Register, _INR(0,2), socketwatch_pollword, bitmask, socket ) );
}

void socketwatch_deregister( int socket )
{
  if ( socketwatch_pollword )
    E_CHECK( _swix( SWI_SocketWatch_Deregister, _INR(0,1), socket, socketwatch_pollword ) );
}

void socketwatch_init( void )
{
  _kernel_oserror *e = _swix( SWI_SocketWatch_AllocPW, _OUT(0), &socketwatch_pollword );
  if ( e )
  {
    socketwatch_pollword = 0;
    syslogf(log_NAME, log_DebugMiscInfo, "Socketwatch could not be initialised (%s), "
            "will use null polls instead", e->errmess);
  }
  else
  {
    *socketwatch_pollword = 0;
  }
}

void socketwatch_finalise( void )
{
  if ( socketwatch_pollword )
    E_CHECK( _swix( SWI_SocketWatch_DeallocPW, _IN(0), socketwatch_pollword ) );
}

#else /* FEATURE_MSGRUTILS */

#include "sys/filio.h"
#include "sys/ioctl.h"
#define MessengerUtils_RegisterClient          0x52587
#define MessengerUtils_DeregisterClient        0x52588
#define MessengerUtils_GetPollWord             0x52580
#define MessengerUtils_AddWatchedFile          0x52581
#define MessengerUtils_RemoveWatchedFile       0x52582
#define MessengerUtils_ClearWatchedFiles       0x52583
#define MessengerUtils_AddWatchedSocket        0x52584
#define MessengerUtils_RemoveWatchedSocket     0x52585
#define MessengerUtils_ClearWatchedSockets     0x52586

static int socketwatch_clienthandle;


void socketwatch_register(int socket)
{
  if (socketwatch_pollword)
  {
    _kernel_oserror *e;
    
    e = _swix(MessengerUtils_AddWatchedSocket, _INR(0,1), socket, socketwatch_clienthandle);
    if (e)
    {
      syslogf(log_NAME, log_OSError, "Could not register socket %d with MessengerUtils (%s)",
              socket, e->errmess);
    }
    else
    {
      int on = 1;
  
      if (ioctl(socket, FIOASYNC, &on) == -1)
      {
        socketwatch_finalise();
      }
    }
  }
}


void socketwatch_deregister( int socket )
{
  if (socketwatch_pollword)
  {
    _kernel_oserror *e;
    e = _swix(MessengerUtils_RemoveWatchedSocket, _INR(0,1), socket, socketwatch_clienthandle);
    E_CHECK(e);
    if (e)
    {
      syslogf(log_NAME, log_OSError, "Could not unregister socket %d with MessengerUtils (%s)",
              socket, e->errmess);
    }
  }
}



void socketwatch_init( void )
{
  _kernel_oserror *e = _swix(MessengerUtils_RegisterClient, _OUTR(0,1),
                              &socketwatch_pollword, &socketwatch_clienthandle);
  if (e)
  {
    socketwatch_pollword = 0;
    socketwatch_clienthandle = 0;
    syslogf(log_NAME, log_DebugMiscInfo, "Could not register with MessengerUtils (%s), "
            "will use null polls instead", e->errmess);
  }
  else
  {
    *socketwatch_pollword = 0;
  }
}


void socketwatch_finalise( void )
{
  if (socketwatch_pollword)
  {
    E_CHECK(_swix(MessengerUtils_DeregisterClient, _IN(1), socketwatch_clienthandle));
    socketwatch_pollword = 0;
    socketwatch_clienthandle = 0;
  }
}


#endif /* FEATURE_MSGRUTILS */
