decodenas.c   [plain text]


/* ************************************************************ *
 *						     		*
 *  Decoding and switching routines for the NAS protocol	*
 *						      		*
 *	James Peterson, 1988			      		*
 *	(c) Copyright MCC, 1988 		      		*
 *						      		*
 * ************************************************************ */

#include "scope.h"
#include "nas.h" 

/*
  There are 4 types of things in NAS: requests, replies, errors, and events.

  Each of them has a format defined by a small integer that defines
  the type of the thing.

  Requests have an opcode in the first byte.
  Events have a code in the first byte.
  Errors have a code in the second byte (the first byte is 0)
  Replies ...

  Replies have a sequence number in bytes 2 and 3.  The sequence
  number should be used to identify the request that was sent, and
  from that request we can determine the type of the reply.
*/


/* ************************************************************ */
/*								*/
/*								*/
/* ************************************************************ */


/*
  We need to keep the sequence number for a request to match it with
  an expected reply.  The sequence number is associated only with the
  particular connection that we have. We would expect these replies
  to be handled as a FIFO queue.
*/

#define DUMP_REQUEST	0
#define DUMP_REPLY	1
#define DUMP_EVENT	2
#define DUMP_ERROR	3

static const char * const simple_names[] = {
    "REQUEST",
    "REPLY  ",
    "EVENT  ",
    "ERROR  ",
};

static void
AudioSimpleDump (int type, FD fd, short Major, short Minor, long bytes)
{
    PrintTime ();
    fprintf (stdout, "@@%s %3d %3d %3d %7ld\n",
	     simple_names[type],
	     ClientNumber(fd),
	     Major, Minor, bytes);
}
	    
/* ************************************************************ */
/*								*/
/*								*/
/* ************************************************************ */

void
DecodeAudioRequest(
    FD fd,
    const unsigned char *buf,
    long    n)
{
  short   Request = IByte (&buf[0]);
  short	  RequestMinor = Request >= 128 ? IByte (&buf[1]) : 0;
  unsigned long	seq;

  CS[fd].SequenceNumber += 1;
  seq = CS[fd].SequenceNumber;
  if (CS[fd].littleEndian) {
    SBf[0] = seq;
    SBf[1] = seq >> 8;
    SBf[2] = seq >> 16;
    SBf[3] = seq >> 24;
  } else {
    SBf[0] = seq >> 24;
    SBf[1] = seq >> 16;
    SBf[2] = seq >> 8;
    SBf[3] = seq;
  }
  SetIndentLevel(PRINTCLIENT);

  if (NasVerbose == 0)
  {
    AudioSimpleDump (DUMP_REQUEST, fd, Request, RequestMinor, n);
    return;
  }
  
  if (NasVerbose > 3)
    DumpItem("Request", fd, buf, n);
  switch (Request)
    {
    case 1:
	AudioListDevices (buf);
	ReplyExpected(fd, Request);
	break;
    case 2:
	AudioGetDeviceAttributes(buf);
	ReplyExpected(fd, Request);
	break;
    case 3:
	AudioSetDeviceAttributes (buf);
	break;
    case 4:
	AudioCreateBucket (buf);
	break;
    case 5:
	AudioDestroyBucket (buf);
	break;
    case 6:
	AudioListBuckets (buf);
	ReplyExpected (fd, Request);
	break;
    case 7:
	AudioGetBucketAttributes (buf);
	ReplyExpected (fd, Request);
	break;
    case 8:
	AudioSetBucketAttributes (buf);
	break;
    case 9:
	AudioCreateRadio (buf);
	break;
    case 10:
	AudioDestroyRadio (buf);
	break;
    case 11:
	AudioListRadios (buf);
	ReplyExpected (fd, Request);
	break;
    case 12:
	AudioGetRadioAttributes (buf);
	ReplyExpected (fd, Request);
	break;
    case 13:
	AudioSetRadioAttributes (buf);
	break;
    case 14:
	AudioCreateFlow (buf);
	break;
    case 15:
	AudioDestroyFlow (buf);
	break;
    case 16:
	AudioGetFlowAttributes (buf);
	ReplyExpected (fd, Request);
	break;
    case 17:
	AudioSetFlowAttributes (buf);
	break;
    case 18:
	AudioGetElements (buf);
	ReplyExpected (fd, Request);
	break;
    case 19:
	AudioSetElements (buf);
	break;
    case 20:
	AudioGetElementStates (buf);
	ReplyExpected (fd, Request);
	break;
    case 21:
	AudioSetElementStates (buf);
	break;
    case 22:
	AudioGetElementParameters (buf);
	ReplyExpected (fd, Request);
	break;
    case 23:
	AudioSetElementParameters (buf);
	break;
    case 24:
	AudioWriteElement (buf);
	break;
    case 25:
	AudioReadElement (buf);
	ReplyExpected (fd, Request);
	break;
    case 26:
	AudioGrabComponent (buf);
	break;
    case 27:
	AudioUngrabComponent (buf);
	break;
    case 28:
	AudioSendEvent (buf);
	break;
    case 29:
	AudioGetAllowedUsers (buf);
	ReplyExpected (fd, Request);
	break;
    case 30:
	AudioSetAllowedUsers (buf);
	break;
    case 31:
	AudioListExtensions (buf);
	ReplyExpected (fd, Request);
	break;
    case 32:
	AudioQueryExtension (buf);
	ReplyExpected (fd, Request);
	break;
    case 33:
	AudioGetCloseDownMode (buf);
	ReplyExpected (fd, Request);
	break;
    case 34:
	AudioSetCloseDownMode (buf);
	break;
    case 35:
	AudioKillClient (buf);
	break;
    case 36:
	AudioGetServerTime (buf);
	ReplyExpected (fd, Request);
	break;
    case 37:
	AudioNoOperation (buf);
	break;
    default:
	warn("Unimplemented request opcode");
	break;
   }
}

/* ************************************************************ */
/*								*/
/*								*/
/* ************************************************************ */

void
DecodeAudioReply(
    FD fd,
    const unsigned char *buf,
    long    n)
{
    short   SequenceNumber = IShort (&buf[2]);
    short	  RequestMinor;
    short   Request = CheckReplyTable (fd, SequenceNumber, &RequestMinor);

    if (NasVerbose == 0)
    {
	AudioSimpleDump (DUMP_REPLY, fd, Request, RequestMinor, n);
	return;
    }

    SetIndentLevel(PRINTSERVER);
    RBf[0] = Request /* for the PrintField in the Reply procedure */ ;
    RBf[1] = RequestMinor;
    if (NasVerbose > 3)
	DumpItem("Reply", fd, buf, n);
    switch (Request)
    {
    case 0:
	UnknownAudioReply(buf);
	break;
    case 1:
	AudioListDevicesReply (buf);
	break;
    case 2:
	AudioGetDeviceAttributesReply (buf);
	break;
    case 6:
	AudioListBucketsReply (buf);
	break;
    case 7:
	AudioGetBucketAttributesReply (buf);
	break;
    case 11:
	AudioListRadiosReply (buf);
	break;
    case 12:
	AudioGetRadioAttributesReply (buf);
	break;
    case 16:
	AudioGetFlowAttributesReply (buf);
	break;
    case 18:
	AudioGetElementsReply (buf);
	break;
    case 20:
	AudioGetElementStatesReply (buf);
	break;
    case 22:
	AudioGetElementParametersReply (buf);
	break;
    case 25:
	AudioReadElementReply (buf);
	break;
    case 29:
	AudioGetAllowedUsersReply (buf);
	break;
    case 31:
	AudioListExtensionsReply (buf);
	break;
    case 32:
	AudioQueryExtensionReply (buf);
	break;
    case 33:
	AudioGetCloseDownModeReply (buf);
	break;
    case 36:
	AudioGetServerTimeReply (buf);
	break;
    default:
	warn("Unimplemented reply opcode");
	break;
    }
}

/* ************************************************************ */
/*								*/
/*								*/
/* ************************************************************ */

void
DecodeAudioError(
    FD fd,
    const unsigned char *buf,
    long    n)
{
    short   Error = IByte (&buf[1]);
    short   Request = 0;
    short   RequestMinor = 0;

    Request = CheckReplyTable (fd, (short)IShort(&buf[2]), &RequestMinor);

    if (NasVerbose == 0)
    {
	AudioSimpleDump (DUMP_ERROR, fd, Request, RequestMinor, n);
	return;
    }

    SetIndentLevel(PRINTSERVER);
    if (NasVerbose > 3)
	DumpItem("Error", fd, buf, n);
}

/* ************************************************************ */
/*								*/
/*								*/
/* ************************************************************ */

void
DecodeAudioEvent(
    FD fd,
    const unsigned char *buf,
    long    n)
{
    short   Event = IByte (&buf[0]);
    short   EventMinor = 0;

    if (NasVerbose == 0) 
    {
	AudioSimpleDump (DUMP_EVENT, fd, Event, EventMinor, n);
	return;
    }

    SetIndentLevel(PRINTSERVER);
    if (NasVerbose > 3)
	DumpItem("Event", fd, buf, n);
    /* high-order bit means SendEvent generated */
    if (Event & 0x80)
    {
	debug(8,(stderr, "SendEvent generated event 0x%x\n", Event));
	Event = Event & 0x7F;
    }
    switch (Event)
    {
    case 2:
	AudioElementNotify (buf);
	break;
    case 3:
	AudioGrabNotify (buf);
	break;
    case 4:
	AudioMonitorNotify (buf);
	break;
    case 5:
	AudioBucketNotify (buf);
	break;
    case 6:
	AudioDeviceNotify (buf);
	break;
    default:
	warn("Unimplemented event code");
	break;
    }
}

void
InitializeAudioDecode (void)
{
    TYPE    p;
    
    p = DefineType (NASREQUEST, ENUMERATED, "NASREQUEST", (PrintProcType) PrintENUMERATED);
    DefineEValue (p, 1L, "ListDevices");
    DefineEValue (p, 2L, "GetDeviceAttributes");
    DefineEValue (p, 3L, "SetDeviceAttributes");
    DefineEValue (p, 4L, "CreateBucket");
    DefineEValue (p, 5L, "DestroyBucket");
    DefineEValue (p, 6L, "ListBuckets");
    DefineEValue (p, 7L, "GetBucketAttributes");
    DefineEValue (p, 8L, "SetBucketAttributes");
    DefineEValue (p, 9L, "CreateRadio");
    DefineEValue (p, 10L, "DestroyRadio");
    DefineEValue (p, 11L, "ListRadios");
    DefineEValue (p, 12L, "GetRadioAttributes");
    DefineEValue (p, 13L, "SetRadioAttributes");
    DefineEValue (p, 14L, "CreateFlow");
    DefineEValue (p, 15L, "DestroyFlow");
    DefineEValue (p, 16L, "GetFlowAttributes");
    DefineEValue (p, 17L, "SetFlowAttributes");
    DefineEValue (p, 18L, "GetElements");
    DefineEValue (p, 19L, "SetElements");
    DefineEValue (p, 20L, "GetElementStates");
    DefineEValue (p, 21L, "SetElementStates");
    DefineEValue (p, 22L, "GetElementParameters");
    DefineEValue (p, 23L, "SetElementParameters");
    DefineEValue (p, 24L, "WriteElement");
    DefineEValue (p, 25L, "ReadElement");
    DefineEValue (p, 26L, "GrabComponent");
    DefineEValue (p, 27L, "UngrabComponent");
    DefineEValue (p, 28L, "SendEvent");
    DefineEValue (p, 29L, "GetAllowedUsers");
    DefineEValue (p, 30L, "SetAllowedUsers");
    DefineEValue (p, 31L, "ListExtensions");
    DefineEValue (p, 32L, "QuerExtension");
    DefineEValue (p, 33L, "GetCloseDownMode");
    DefineEValue (p, 34L, "SetCloseDownMode");
    DefineEValue (p, 35L, "KillClient");
    DefineEValue (p, 36L, "GetServerTime");
    DefineEValue (p, 37L, "NoOperation");
    p = DefineType (NASREPLY, ENUMERATED, "NASREPLY", (PrintProcType) PrintENUMERATED);
    DefineEValue (p, 1L, "ListDevices");
    DefineEValue (p, 2L, "GetDeviceAttributes");
    DefineEValue (p, 6L, "ListBuckets");
    DefineEValue (p, 7L, "GetBucketAttributes");
    DefineEValue (p, 11L, "ListRadios");
    DefineEValue (p, 12L, "GetRadioAttributes");
    DefineEValue (p, 16L, "GetFlowAttributes");
    DefineEValue (p, 18L, "GetElements");
    DefineEValue (p, 20L, "GetElementStates");
    DefineEValue (p, 22L, "GetElementParameters");
    DefineEValue (p, 25L, "ReadElement");
    DefineEValue (p, 29L, "GetAllowedUsers");
    DefineEValue (p, 31L, "ListExtensions");
    DefineEValue (p, 32L, "QueryExtension");
    DefineEValue (p, 33L, "GetCloseDownMode");
    DefineEValue (p, 36L, "GetServerTime");
    p = DefineType (NASEVENT, ENUMERATED, "NASEVENT", (PrintProcType) PrintENUMERATED);
    DefineEValue(p, 2L, "ElementNotify");
    DefineEValue(p, 3L, "GrabNotify");
    DefineEValue(p, 4L, "MonitorNotify");
    DefineEValue(p, 5L, "BucketNotify");
    DefineEValue(p, 6L, "DeviceNotify");
    
}