/* ************************************************************ * * * * 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"); }