OpenContinue Extra Header

 
CU-SeeMe Development Group
Document Draft:  001
Protocol Feature Designer: Tim Dorcey, td11@cornell.edu
Document Author: Richard Kennerly, rbk1@cornell.edu
Revised: Feb 26, 1996

Protocol Specification - Adding "Extra Data" to CU-SeeMe OpenContinue Packets

Status:
-------
Implemented in Mac CU-SeeMe 0.80b2 and earlier
Implemented in Windows CU-SeeMe 0.70b1
                    
				
Abstract:
---------

   We need a way to extend the OpenContinue packet to include additional types
of information for enhancements or add-on's to the protocol.  The mechanism
described below allows us to add chunks of different kinds of data to the
end of OpenContinue Packets after the ClientInfo structures.


Definitions:
------------

   Define the types of "extra" data to be appended to OpenContinue Packets.

#define kAuxTMAdvExtraType      1       // Advertise AUX Data bit mapping
#define kRateReportExtraType    2       // Report Rate Parameters
#define kVersionReportExtraType 4       // New Version information scheme


Packet Format:
--------------

   The Extra Data is preceeded by an OCExtraHeader:

typedef struct {
   short            oeh_dataType;       // Extra Data Type, e.g.
                                        // kAuxTMAdvExtraType, 
                                        // kRateReportExtraType
   unsigned short   oeh_length;         // Length of Extra Data in bytes,
                                        // must be a multiple of 4 bytes
} OCExtraHeader;

   The format of the extra data itself is not defined here and depends on what
the extra data type is.


   The format of an entire OpenContinue Packet with Extra Data is:

BigOpenContinuePacket {
   OpenContinuePacket {
      VideoPacketHeader {
         ->PacketLength field modified <<-------
      }
      OpenContinueData {
      }
   }
   ClientInfo [OpenContinueData->ClientCount] {
   }
   OCExtraHeader {
   }
   (Extra Data Structure specified in OCExtraHeader)
   ...
   more optional OCExtraHeader / Extra Data structure pairs
   ...
}


Packet Generation:
------------------

   A sender wishing to transmit extra data to an OpenContinue Packet constructs
the packet up to and including the ClientInfo structs for each client.  After
this an OCExtraHeader structure is added.  Immediately following this is the
structure for the extra data.  The format and length of this structure depends
on the type of data and will not be discussed here.  One or more such
additions can be made to the packet.  The length element in the
VideoPacketHeader structure is adjusted to include the length of the new
extra data.  This length field now includes the OpenContinuePacketLength,
all of the ClientInfo Structures and any OCExtraHeader and Extra Data
structures.


Packet Reception and Processing:
--------------------------------

   A receiver processes the OpenContinue Packet up until and including the
ClientInfo structures.  If the length specified in the VideoPacketHeader->
PacketLength field is greater than the packet data, then it is assumed that
an OCExtraHeader follows.  The receiver application looks at the dataType
field of the OCExtraHeader and, if it knows what to do with the extra data,
processes it.  It then checks to see if there is remaining data in the packet
and repeats this process until there is no more data left.


Sample Code for Packet Reception (from Windows Version R36)
--------------------------------


/* 
   GetOCExtraData ()
   
   See if there is any extra data at the end of the OpenContinue
   Packet and, if so, process it.
   
*/
       
BOOL   GetOCExtraData(OPENCONTINUEPACKET * pocp, PVC pvc)
{
   CLIENTINFO     *cli;
   OCExtraHeader  *oce;
	int             iPktLen;
   BIGOCP         *bmf = (BIGOCP*) pocp;

   if (pvc == NULL) {
      return (FALSE);
   }
   iPktLen = ntohs(pocp->ocp_header.vph_packetLength);
   iPktLen -= (sizeof(OPENCONTINUEPACKET)
      + (sizeof(CLIENTINFO) * ntohs(pocp->ocp_config.ocd_clientCount)));
   if (iPktLen <= 0) {
      return (FALSE);   // No extra Data
   }
   cli = (CLIENTINFO *) (pocp + 1);
   oce = (OCExtraHeader *) (cli + ntohs(pocp->ocp_config.ocd_clientCount));

   while (iPktLen > sizeof(OCExtraHeader)) {
      // Note: ntohs() returns an unsigned short so we won't get negative val's
      if ((UINT)iPktLen < ntohs(oce->oeh_bytes) + sizeof(OCExtraHeader)) {
         return (FALSE);
      }
      switch (ntohs(oce->oeh_dataType)) {
      case kRateReportExtraType:
         ProcessRateReportData((RateReportData *) (oce + 1), pvc);
         break;
      case kVersionReportExtraType:
         ProcessVersionReport((VersionData *) (oce + 1), pvc);
         break;
      case kAuxTMAdvExtraType:
         if (CC_Aux_ProcAdv( pocp, pvc )) {
            pvc->vcx_cliflags |= UPDATE_AUXDATA;
            UpdateOCIncrement(OC_UPDATE);
         }
         break;
      default:   // Extra Data that we don't handle
         break;
      }
      if (ntohs(oce->oeh_bytes) == 0) {	// broken packet
         break;
      }
      iPktLen -= (sizeof(OCExtraHeader) + ntohs(oce->oeh_bytes));
      oce = (OCExtraHeader *) ((BYTE *) oce + sizeof(OCExtraHeader) 
            + ntohs(oce->oeh_bytes));
   }
   return (TRUE);
}