#include <cdevMessageBinary.h>

const unsigned BIT01 = 1;
const unsigned BIT02 = 2;
const unsigned BIT03 = 4;
const unsigned BIT04 = 8;
const unsigned BIT05 = 16;
const unsigned BIT06 = 32;
const unsigned BIT07 = 64;
const unsigned BIT08 = 128;
const unsigned BIT09 = 256;
const unsigned BIT10 = 512;
const unsigned BIT11 = 1024;
const unsigned BIT12 = 2048;
const unsigned BIT13 = 4096;
const unsigned BIT14 = 8192;
const unsigned BIT15 = 16384;
const unsigned BIT16 = 32768;

// *****************************************************************************
// * cdevMessageBinary::map2int ( void )
// *	This method will convert the cdevMessageBinaryMap to a long integer.
// *****************************************************************************
unsigned cdevMessageBinary::map2int ( cdevMessageBinaryMap mapdata, unsigned & value)
	{
	value = (mapdata.value.version << 16);
	if(mapdata.value.clientIDSet!=0)         value |= BIT16;
	if(mapdata.value.transIndexSet!=0)       value |= BIT15;
	if(mapdata.value.cancelTransIndexSet!=0) value |= BIT14;
	if(mapdata.value.localDataIndexSet!=0)   value |= BIT13;
	if(mapdata.value.foreignDataIndexSet!=0) value |= BIT12;
	if(mapdata.value.operationCodeSet!=0)    value |= BIT11;
	if(mapdata.value.completionCodeSet!=0)   value |= BIT10;
	if(mapdata.value.deviceListSet!=0)       value |= BIT09;
	if(mapdata.value.messageSet!=0)          value |= BIT08;
	if(mapdata.value.dataSet!=0)             value |= BIT07;
	if(mapdata.value.contextSet!=0)          value |= BIT06;
	if(mapdata.value.tagMapSet!=0)           value |= BIT05;
	return value;
	}

// *****************************************************************************
// * cdevMessageBinary::int2map ( void )
// *	This method will convert a long  integer to a cdevMessageBinaryMap.
// *****************************************************************************
cdevMessageBinaryMap cdevMessageBinary::int2map ( cdevMessageBinaryMap &mapdata, unsigned value)
	{
	mapdata.rawData                   = 0;
	mapdata.value.version             = (value >> 16);
	mapdata.value.clientIDSet         = (value & BIT16)?1:0;
	mapdata.value.transIndexSet       = (value & BIT15)?1:0;
	mapdata.value.cancelTransIndexSet = (value & BIT14)?1:0;
	mapdata.value.localDataIndexSet   = (value & BIT13)?1:0;
	mapdata.value.foreignDataIndexSet = (value & BIT12)?1:0;
	mapdata.value.operationCodeSet    = (value & BIT11)?1:0;
	mapdata.value.completionCodeSet   = (value & BIT10)?1:0;
	mapdata.value.deviceListSet       = (value & BIT09)?1:0;
	mapdata.value.messageSet          = (value & BIT08)?1:0;
	mapdata.value.dataSet             = (value & BIT07)?1:0;
	mapdata.value.contextSet          = (value & BIT06)?1:0;
	mapdata.value.tagMapSet           = (value & BIT05)?1:0;
	return mapdata;	
	}

// *****************************************************************************
// * cdevMessageBinary::cdevMessageBinary :
// *	Copy constructaor for the class.  Sets all of the variables to the
// *	values stored in the referenced objects.
// *****************************************************************************
cdevMessageBinary::cdevMessageBinary ( cdevMessageBinary & packet )
	: cdevPacketBinary()
	{
	streamIn(packet.binary, packet.binaryLen);
	}

		
// *****************************************************************************
// * cdevMessageBinary::cdevMessageBinary :
// *	This is the default and parameterized constructor. Allows the caller to 
// *    directly specify each of the components.
// *****************************************************************************
cdevMessageBinary::cdevMessageBinary ( short            clientID, 
				       unsigned         transIndex, 
				       unsigned         cancelTransIndex,
				       unsigned         localDataIndex, 
				       unsigned         foreignDataIndex,
				       unsigned         operationCode,
				       int              completionCode,
				       unsigned         deviceCount,
				       char **          deviceList,
				       char *           message,
				       cdevData *       data,
				       cdevData *       context,
				       cdevData *       tagMap)
	: cdevPacketBinary()
	{
	set(clientID, transIndex, cancelTransIndex, localDataIndex, 
	    foreignDataIndex, operationCode, completionCode, deviceCount, 
	    deviceList, message, data, context, tagMap);
	}


// *****************************************************************************
// * cdevMessageBinary::~cdevMessageBinary :
// *	This is the destructor for the class.  
// *****************************************************************************
cdevMessageBinary::~cdevMessageBinary ( void )
	{
	// *********************************************************************
	// * Execute a detach on the embedded data to ensure that it is not
	// * deleted locally.
	// *********************************************************************
	reader.detachData();
	}
	

// *****************************************************************************
// * cdevMessageBinary::streamIn :
// *	The streamIn function will read a memory buffer provided by the caller 
// *	and then populate the class with these values. This stream remains the 
// *	property of the caller and he is responsible for deleting it.
// *****************************************************************************
int cdevMessageBinary::streamIn ( char *stream, size_t len )
	{
	int      result = -1;
	unsigned packetMap = 0;
			
	// *********************************************************************
	// * Delete the binary data buffer and set its length to 0.
	// *********************************************************************
	if(binary!=NULL) 
		{
		delete binary;
		binary = NULL;
		}
	binaryLen = 0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(stream, len);
	
	// *********************************************************************
	// * Clear the packet map prior to reading data from the stream.
	// *********************************************************************
	map.rawData       = 0;
	
	// *********************************************************************
	// * Read the packet map from the stream.  This object contains a bit
	// * field that identifies the version of the packet and tells what 
	// * other components are embedded in the binary stream.
	// *********************************************************************
	result = !reader.get(packetMap);
	int2map (map, packetMap);
	
	// *********************************************************************
	// * Before processing anything else, the method must ensure that this
	// * packet is of the correct version.  Version 1 for this object.
	// *
	// * Note that reading each field is contingent on the prior fields 
	// * being read correctly.
	// *********************************************************************
	if(!result && map.value.version == CDEV_PACKET_VERSION)
		{		
		binaryLen = len;
		binary    = new char[binaryLen];
		memcpy(binary, stream, binaryLen);
		}
	else result = -1;
	
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *********************************************************************
// * cdevMessageBinary::attachData :
// *	This method allows the caller to assign a preallocated binary
// *	buffer to this object.  This prevents the cdevMessageBinary class
// *	from having to allocate the data.
// *********************************************************************
int cdevMessageBinary::attachData ( char * stream, size_t len )
	{
	int      result = -1;
	unsigned packetMap = 0;			

	// *********************************************************************
	// * Delete the binary data buffer and set its length to 0.
	// *********************************************************************
	if(binary!=NULL) 
		{
		delete binary;
		binary = NULL;
		}
	binaryLen = 0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(stream, len);
	
	// *********************************************************************
	// * Clear the packet map prior to reading data from the stream.
	// *********************************************************************
	map.rawData       = 0;
	
	// *********************************************************************
	// * Read the packet map from the stream.  This object contains a bit
	// * field that identifies the version of the packet and tells what 
	// * other components are embedded in the binary stream.
	// *********************************************************************
	result = !reader.get(packetMap);
	int2map (map, packetMap);
	
	// *********************************************************************
	// * Before processing anything else, the method must ensure that this
	// * packet is of the correct version.  Version 1 for this object.
	// *
	// * Note that reading each field is contingent on the prior fields 
	// * being read correctly.
	// *********************************************************************
	if(!result && map.value.version == CDEV_PACKET_VERSION)
		{		
		binaryLen = len;
		binary = stream;
		}
	else result = -1;
	
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::asciiDump :
// *	This method performs a diagnostic dump of the text representation of the
// *	packets contents.
// *****************************************************************************
void cdevMessageBinary::asciiDump ( FILE * fp )
	{
	short clientID;
	unsigned transIndex, cancelTransIndex, localDataIndex;
	unsigned foreignDataIndex, operationCode, deviceCount;
	int completionCode;
	char **  deviceList;
	char *   message;
	cdevData temp;

	getClientID(clientID);
	getTransIndex(transIndex);
	getCancelTransIndex(cancelTransIndex);
	getLocalDataIndex(localDataIndex);
	getForeignDataIndex(foreignDataIndex);
	getOperationCode (operationCode);
	getCompletionCode (completionCode);
	getDeviceList(deviceList, deviceCount);
	getMessage(message);
	
	fprintf(fp, "----------------------------------------------------------\n");
	fprintf(fp, "             Diagnostic Dump of CDEV Packet\n");
	fprintf(fp, "----------------------------------------------------------\n\n");
	fprintf(fp, "Packet Version     : %i\n", CDEV_PACKET_VERSION);
	fprintf(fp, "Binary Stream Size : %i\n", binaryLen);
	fprintf(fp, "Client Identifier  : %s\n", clientID==-1?"(not specified)":ltoa(clientID));
	fprintf(fp, "Transaction Index  : %s\n", transIndex==0?"(not specified)":ultoa(transIndex));
	fprintf(fp, "Cancel Transaction : %s\n", cancelTransIndex==0?"(not specified)":ultoa(cancelTransIndex));
	fprintf(fp, "Local Data Index   : %s\n", localDataIndex==0?"(not specified)":ultoa(localDataIndex));
	fprintf(fp, "Foreign Data Index : %s\n", foreignDataIndex==0?"(not specified)":ultoa(foreignDataIndex));
	fprintf(fp, "Operation Code     : %s\n", operationCode==0?"(not specified)":ultoa(operationCode));
	fprintf(fp, "Completion Code    : %i\n", completionCode);
	fprintf(fp, "Number of Devices  : %s\n", deviceCount==0?"(not specified)":ultoa(deviceCount));
	fprintf(fp, "List of Devices    : ");
	
	if(deviceCount==0) fprintf(fp, "(not specified)\n");
	else fprintf(fp, "%s\n", deviceList[0]);
	
	for(int i=1; i<deviceCount; i++) 
		{
		fprintf(fp, "                     %s\n", deviceList[i]);
		}

	fprintf(fp, "Message String     : %s\n", message==NULL?"(not specified)":message);

	// *********************************************************************
	// * The deviceList and message string must be deleted.
	// *********************************************************************
	if(deviceList!=NULL)
		{
		for(i=0; i<deviceCount; i++) delete deviceList[i];
		delete deviceList;
		}		
	if(message != NULL) delete message;
	
	int empty;
	
	fprintf(fp, "Data Object        : %s", (empty=getData(temp))==0?"\n":"(not specified)\n");
	fflush(fp);
	if(!empty) temp.asciiDump(fp);
	
	fprintf(fp, "Context Object     : %s", (empty=getContext(temp))==0?"\n":"(not specified)\n");
	fflush(fp);
	if(!empty) temp.asciiDump(fp);
	
	fprintf(fp, "Tag Map            : %s", (empty=getTagMap(temp))==0?"\n":"(not specified)\n");
	if(!empty)
		{
		size_t  tagNumCnt  = 0;
		int  *  tagNums    = NULL;
		size_t  tagNameCnt = 0;
		
		if(temp.getElems(1, &tagNumCnt)==CDEV_SUCCESS  && 
		   temp.getElems(2, &tagNameCnt)==CDEV_SUCCESS &&
		   temp.getType (2)==CDEV_STRING               &&
		   tagNumCnt==tagNameCnt)
			{
			char ** tagNames   = NULL;
			char *  singleName = NULL;
	
			tagNums = new int[tagNumCnt];
			temp.get(1, tagNums);

			if(tagNameCnt==1)
				{
				tagNames = &singleName;
				temp.find(2, (void *&)singleName);
				}
			else temp.find(2, (void *&)tagNames);

			for(int i=0; i<tagNumCnt; i++)
				{
				fprintf(fp, "\t%-26.26s= %i\n", tagNames[i], tagNums[i]);
				} 
			delete tagNums;
			}
		}
	fprintf(fp, "----------------------------------------------------------\n");
	fprintf(fp, "            End of Diagnostic Dump of CDEV Packet\n");
	fprintf(fp, "----------------------------------------------------------\n\n");
	fflush(fp);
	}


// *****************************************************************************
// * cdevMessageBinary::setBinaryPosition :
// *	This method will set the position of the binary stream within an 
// *	XDR_Reader to the specified data object.
// *	This method returns 0 on success, or -1 if the data object could not be
// *	selected.
// *****************************************************************************
int cdevMessageBinary::setBinaryPosition (XDR_Reader & Reader, POSITION_FLAG flag )
	{
	int      slen;
	int      result    = -1;
	unsigned packetMap = 0;

	// *********************************************************************
	// * Set the position to the beginning of the data buffer.
	// *********************************************************************
	xdr_setpos(Reader.xdr(), 0);
			
	// *********************************************************************
	// * Clear the packet map prior to reading data from the stream.
	// *********************************************************************
	map.rawData       = 0;
	
	// *********************************************************************
	// * Read the packet map from the stream.  This object contains a bit
	// * field that identifies the version of the packet and tells what 
	// * other components are embedded in the binary stream.
	// *********************************************************************
	result = !Reader.get(packetMap);
	int2map ( map, packetMap );

	// *********************************************************************
	// * Before processing anything else, the method must ensure that this
	// * packet is of the correct version.  Version 1 for this object.
	// *
	// * Note that reading each field is contingent on the prior fields 
	// * being read correctly.
	// *********************************************************************
	if(!result && map.value.version==CDEV_PACKET_VERSION)
		{		
		// *************************************************************
		// * If the selected element is beyond the clientID, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_CLIENTID)
			{
			if(map.value.clientIDSet!=0)
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((short)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the clientID.
		// *************************************************************
		else if(flag==GOTO_CLIENTID && !map.value.clientIDSet) result=-1;


		// *************************************************************
		// * If the selected element is beyond the transIndex, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_TRANSINDEX)
			{
			if(!result && map.value.transIndexSet!=0)
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the transIndex.
		// *************************************************************
		else if(flag==GOTO_TRANSINDEX && !map.value.transIndexSet) result=-1;
			
			

		// *************************************************************
		// * If the selected element is beyond the cancelTransIndex, 
		// * then advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_CANCELTRANSINDEX)
			{
			if(!result && map.value.cancelTransIndexSet!=0)
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the cancelTransIndex.
		// *************************************************************
		else if(flag==GOTO_CANCELTRANSINDEX && !map.value.cancelTransIndexSet) result=-1;
			
			

		// *************************************************************
		// * If the selected element is beyond the localDataIndex, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_LOCALDATAINDEX)
			{
			if(!result && map.value.localDataIndexSet!=0) 
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the localDataIndex.
		// *************************************************************
		else if(flag==GOTO_LOCALDATAINDEX && !map.value.localDataIndexSet) result=-1;
			
			

		// *************************************************************
		// * If the selected element is beyond the foreignDataIndex, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_FOREIGNDATAINDEX)
			{
			if(!result && map.value.foreignDataIndexSet!=0) 
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the foreignDataIndex.
		// *************************************************************
		else if(flag==GOTO_FOREIGNDATAINDEX && !map.value.foreignDataIndexSet) result=-1;
			
		

		// *************************************************************
		// * If the selected element is beyond the operationCode, 
		// * then advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_OPERATIONCODE)
			{
			if(!result && map.value.operationCodeSet!=0)
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((unsigned)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the operationCode.
		// *************************************************************
		else if(flag==GOTO_OPERATIONCODE && !map.value.operationCodeSet) result=-1;
			

			
		// *************************************************************
		// * If the selected element is beyond the operationCode, 
		// * then advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_COMPLETIONCODE)
			{
			if(!result && map.value.completionCodeSet!=0)
			    result=!xdr_setpos(
				Reader.xdr(), 
				xdr_getpos(Reader.xdr())+XDR_Sizeof((int)1));
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the operationCode.
		// *************************************************************
		else if(flag==GOTO_COMPLETIONCODE && !map.value.completionCodeSet) result=-1;


		// *************************************************************
		// * If the selected element is beyond the deviceList, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_DEVICELIST)
			{
			if(!result && map.value.deviceListSet!=0)
				{
				int deviceCount;
				if((result = !Reader.get(deviceCount))==0)
					{
					// *************************************
					// * Step over each string in the array.
					// *************************************
					for(int i=0; i<deviceCount && !result; i++)
						{
						slen   = Reader.get_string_len();
						slen   = XDR_Sizeof((char *)NULL, slen);
						result = !xdr_setpos(
								Reader.xdr(), 
								xdr_getpos(Reader.xdr())+slen); 
						}
					}
				}
			}			
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the deviceList.
		// *************************************************************
		else if(flag==GOTO_DEVICELIST && !map.value.deviceListSet) result=-1;
	


		// *************************************************************
		// * If the selected element is beyond the message, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_MESSAGE)
			{
			if(!result && map.value.messageSet!=0)
				{
				slen   = Reader.get_string_len();
				slen   = XDR_Sizeof((char *)NULL, slen);
				result = !xdr_setpos(
						Reader.xdr(), 
						xdr_getpos(Reader.xdr())+slen); 
				}
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the message.
		// *************************************************************
		else if(flag==GOTO_MESSAGE && !map.value.messageSet) result=-1;



		// *************************************************************
		// * If the selected element is beyond the data, then 
		// * advance the buffer to the next item.
		// *************************************************************
		if(flag > GOTO_DATA)
			{
			if(!result && map.value.dataSet!=0)
				{
				slen   = Reader.get_string_len();
				slen   = XDR_Sizeof((void *)NULL, slen);
				result = !xdr_setpos(
						Reader.xdr(), 
						xdr_getpos(Reader.xdr())+slen); 
				}
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the data.
		// *************************************************************
		else if(flag==GOTO_DATA && !map.value.dataSet) result=-1;
		
		
		
		// *************************************************************
		// * If the selected element is beyond the context, then it
		// * contains an invalid value and should be cleared.
		// *************************************************************
		if(flag > GOTO_CONTEXT)
			{
			if(!result && map.value.contextSet!=0)
				{
				slen   = Reader.get_string_len();
				slen   = XDR_Sizeof((void *)NULL, slen);
				result = !xdr_setpos(
						Reader.xdr(), 
						xdr_getpos(Reader.xdr())+slen); 
				}			
			}
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the context.
		// *************************************************************
		else if(flag==GOTO_CONTEXT && !map.value.contextSet) result=-1;


		// *************************************************************
		// * If the selected element is beyond the context, then it
		// * contains an invalid value and should be cleared.
		// *************************************************************
		if(flag > GOTO_TAGMAP) result = -1;
		// *************************************************************
		// * Otherwise... set the result to indicate the existence (or
		// * non-existence) of the context.
		// *************************************************************
		else if(flag==GOTO_TAGMAP && !map.value.tagMapSet) result=-1;
		}

	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::set :
// *	This method will convert the user provided data into the binary stream.
// *****************************************************************************
void cdevMessageBinary::set ( short            clientID, 
			      unsigned         transIndex, 
			      unsigned         cancelTransIndex,
			      unsigned         localDataIndex, 
			      unsigned         foreignDataIndex,
			      unsigned         operationCode,
			      int              completionCode,
			      unsigned         deviceCount,
			      char **          deviceList,
			      char *           message,
			      cdevData *       data,
			      cdevData *       context,
			      cdevData *       tagMap)
	{
	unsigned packetMap  = 0;
	size_t   dataLen    = 0, dataCnt    = 0;
	size_t   contextLen = 0, contextCnt = 0;
	size_t   tagMapLen  = 0, tagMapCnt  = 0;
	
	if(binary!=NULL) 
		{
		delete binary;
		binary = NULL;
		}
	binaryLen = 0;
	
	// *********************************************************************
	// * Construct the packet map to indicate which components will be 
	// * transmitted.
	// *********************************************************************
	map.rawData       = 0;
	map.value.version = CDEV_PACKET_VERSION;
	
	// *********************************************************************
	// * Because the cdevPacketBinary relies on the ordered existance of the
	// * client identifier... this entry will automatically be tagged as 
	// * present, even though it may contain a default value...
	// *********************************************************************
	map.value.clientIDSet = 1;
	
	// *********************************************************************
	// * All other components will only be marked as present if they have 
	// * actually been specified.
	// *********************************************************************
	if(transIndex > 0)                    map.value.transIndexSet = 1;
	if(cancelTransIndex > 0)              map.value.cancelTransIndexSet = 1;
	if(localDataIndex > 0)                map.value.localDataIndexSet = 1;
	if(foreignDataIndex > 0)              map.value.foreignDataIndexSet = 1;
	if(operationCode > 0)                 map.value.operationCodeSet = 1;
	if(completionCode != 0)               map.value.completionCodeSet = 1;
	if(deviceCount>0 && deviceList!=NULL) map.value.deviceListSet = 1;
	if(message!=NULL)                     map.value.messageSet = 1;
	
	if(data!=NULL)    data->xdrSize   (&dataLen, &dataCnt);
	if(context!=NULL) context->xdrSize(&contextLen, &contextCnt);
	if(tagMap!=NULL)  tagMap->xdrSize (&tagMapLen, &tagMapCnt);
	
	if(dataCnt > 0)                       map.value.dataSet = 1;
	if(contextCnt > 0)                    map.value.contextSet = 1;
	if(tagMapCnt > 0)                     map.value.tagMapSet = 1;
	
	// *********************************************************************
	// * Calculate the total size of the packet.
	// *********************************************************************
	binaryLen = XDR_Sizeof( map2int(map, packetMap) );
	if(map.value.clientIDSet!=0)             binaryLen += XDR_Sizeof(clientID);
	if(map.value.transIndexSet!=0)           binaryLen += XDR_Sizeof(transIndex);
	if(map.value.cancelTransIndexSet!=0)     binaryLen += XDR_Sizeof(cancelTransIndex);
	if(map.value.localDataIndexSet!=0)       binaryLen += XDR_Sizeof(localDataIndex);
	if(map.value.foreignDataIndexSet!=0)     binaryLen += XDR_Sizeof(foreignDataIndex);
	if(map.value.operationCodeSet!=0)        binaryLen += XDR_Sizeof(operationCode);
	if(map.value.completionCodeSet!=0)       binaryLen += XDR_Sizeof(completionCode);
	if(map.value.deviceListSet!=0)
		{
		binaryLen += XDR_Sizeof(deviceCount);
		for(int i=0; i<deviceCount; i++) binaryLen += XDR_Sizeof(deviceList[i]);
		}
	if(map.value.messageSet!=0)              binaryLen += XDR_Sizeof(message);
	if(map.value.dataSet!=0)
		{
		binaryLen += XDR_Sizeof((void *)NULL, dataLen);
		}
	if(map.value.contextSet!=0)
		{
		binaryLen += XDR_Sizeof((void *)NULL, contextLen);
		}
	if(map.value.tagMapSet!=0)
		{
		binaryLen += XDR_Sizeof((void *)NULL, tagMapLen);
		}
		
	// *********************************************************************
	// * Allocate the packet and then write the data items into it.
	// *********************************************************************
	XDR_Writer writer;
	unsigned   position = 0;
	
	binary = new char[binaryLen];
	writer.attachData(binary, binaryLen);
	writer.put(packetMap);
	if(map.value.clientIDSet!=0)             writer.put(clientID);
	if(map.value.transIndexSet!=0)           writer.put(transIndex);
	if(map.value.cancelTransIndexSet!=0)     writer.put(cancelTransIndex);
	if(map.value.localDataIndexSet!=0)       writer.put(localDataIndex);
	if(map.value.foreignDataIndexSet!=0)     writer.put(foreignDataIndex);
	if(map.value.operationCodeSet!=0)        writer.put(operationCode);
	if(map.value.completionCodeSet!=0)       writer.put(completionCode);
	if(map.value.deviceListSet!=0)
		{
		writer.put(deviceCount);
		for(int i=0; i<deviceCount; i++) writer.put((char *)deviceList[i]);
		}
	if(map.value.messageSet!=0)              writer.put((char *)message);

	// *********************************************************************
	// * This is an experimental insertion that allows me to place the data
	// * into the xdr buffer directly without having to preallocate a buffer.
	// *********************************************************************
	char * tbuf;
	int    tpos;

	if(map.value.dataSet!=0) 
		{
		tpos = xdr_getpos(writer.xdr());
		writer.put(dataLen);
		tbuf = writer.buffer()+xdr_getpos(writer.xdr());
		data->xdrExport(tbuf, dataLen, dataCnt);
		xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, dataLen));
		}
	if(map.value.contextSet!=0)
		{
		tpos = xdr_getpos(writer.xdr());
		writer.put(contextLen);
		tbuf = writer.buffer()+xdr_getpos(writer.xdr());
		context->xdrExport(tbuf, contextLen, contextCnt);
		xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, contextLen));
		}
	if(map.value.tagMapSet!=0)
		{
		tpos = xdr_getpos(writer.xdr());
		writer.put(tagMapLen);
		tbuf = writer.buffer()+xdr_getpos(writer.xdr());
		tagMap->xdrExport(tbuf, tagMapLen, tagMapCnt);
		xdr_setpos(writer.xdr(), tpos+XDR_Sizeof((void *)NULL, tagMapLen));
		}

	writer.detachData();
	}


// *****************************************************************************
// * cdevMessageBinary::getVersion :
// *	This method is used to obtain the version number of the packet.
// *****************************************************************************
int cdevMessageBinary::getVersion ( short & version )
	{
	version = CDEV_PACKET_VERSION;
	return 0;
	}


// *****************************************************************************
// * cdevMessageBinary::getClientID :
// *	This method is used to obtain the client identifier for the packet.
// *	This method returns 0 on success, or -1 if the clientID was not
// *	specified.
// *****************************************************************************
int cdevMessageBinary::getClientID ( short & clientID )
	{
	int  result = -1;
	clientID    = -1;
			
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_CLIENTID))==0)
		{
		if(map.value.clientIDSet!=0)  result=!reader.get(clientID);
		}

	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


	
// *****************************************************************************
// * cdevMessageBinary::getTransIndex :
// *	This method is used to obtain the transaction object index.  This
// *	object is used on the client side to obtain a pointer to the transaction
// *	object.
// *	This method returns 0 on success, or -1 if the transIndex could not
// *	be read.
// *****************************************************************************
int cdevMessageBinary::getTransIndex ( unsigned & transIndex )
	{
	int    result = -1;
	transIndex    = 0;
			
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_TRANSINDEX))==0)
		{
		result = !reader.get(transIndex);
		}

	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getCancelTransIndex :
// *	This method is used to obtain the identifier of a transaction object
// *	that is to be canceled.
// *
// *	This method returns 0 on success, or -1 if the cancelCancelTransIndex could not
// *	be read.
// *****************************************************************************
int cdevMessageBinary::getCancelTransIndex ( unsigned & cancelTransIndex )
	{
	int result       = -1;
	cancelTransIndex = 0;
			
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_CANCELTRANSINDEX))==0)
		{
		result = !reader.get(cancelTransIndex);
		}

	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getLocalDataIndex :
// *	This method is used to obtain an index to any data that may be 
// *	maintained on the senders side of the connection.
// *	This method returns 0 on success, or -1 if the localDataIndex could 
// *	not be read.
// *****************************************************************************
int cdevMessageBinary::getLocalDataIndex ( unsigned & localDataIndex )
	{
	int    result  = -1;
	localDataIndex =  0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_LOCALDATAINDEX))==0)
		{
		result = !reader.get(localDataIndex);
		}
		
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getForeignDataIndex :
// *	This method is used to obtain an index to any data that may be 
// *	maintained on the senders side of the connection.
// *	This method returns 0 on success, or -1 if the foreignDataIndex could 
// *	not be read.
// *****************************************************************************
int cdevMessageBinary::getForeignDataIndex ( unsigned & foreignDataIndex )
	{
	int    result    = -1;
	foreignDataIndex = 0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_FOREIGNDATAINDEX))==0)
		{
		result = !reader.get(foreignDataIndex);
		}
		
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getOperationCode :
// *	This method is used to obtain the operation code.  An operation code may
// *	be used by the developer to define a particular message.  This is faster
// *	to manipulate than the supported string messages.
// *****************************************************************************
int cdevMessageBinary::getOperationCode ( unsigned & operationCode )
	{
	int result         = -1;
	operationCode = 0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_OPERATIONCODE))==0)
		{
		result = !reader.get(operationCode);
		}
		
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getCompletionCode :
// *	This method is used to obtain the completion code.  The completion code
// *	is returned by the server to indicate the result code from an operation.
// *****************************************************************************
int cdevMessageBinary::getCompletionCode ( int & completionCode )
	{
	int result         = -1;
	completionCode = 0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_COMPLETIONCODE))==0)
		{
		result = !reader.get(completionCode);
		}
		
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}

// *****************************************************************************
// * cdevMessageBinary::getDeviceList :
// *	This method is used to obtains an array of device names that are 
// *	associated with the request.  It is the responsibility of the caller
// *	to delete each element of the array, and the array itself when they
// *	are no longer needed.
// *	This method returns 0 on success, or -1 if the deviceList could 
// *	not be read.
// *****************************************************************************
int cdevMessageBinary::getDeviceList ( char ** & deviceList, unsigned & deviceCount)
	{
	int    result = -1;

	deviceList  = NULL;
	deviceCount = 0;

	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_DEVICELIST))==0)
		{
		if((result = !reader.get(deviceCount))==0)
			{
			// *********************************************
			// * Allocate and initialize an array sufficient
			// * to hold the contents of the stream.
			// *********************************************
			deviceList = new char * [deviceCount];
			memset(deviceList, 0, sizeof(char *)*deviceCount);

			// *********************************************
			// * Read the individual strings into the array.
			// * Note that the XDR_Reader will automatically
			// * allocate data if the pointers are set to 
			// * NULL.
			// *********************************************
			for(int i=0; i<deviceCount && !result; i++)
				result = !reader.get(&deviceList[i]);
			}

		// *****************************************************
		// * In event that a failure occurred after the buffer
		// * was allocated.  Walk through the array and free
		// * each data item... then free the array.
		// *****************************************************
		if(result!=0 && deviceList!=NULL)
			{
			for(int i=0; i<deviceCount; i++)
				{
				if(deviceList[i]!=NULL) delete deviceList[i];
				}
			delete deviceList;
			}
		}
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getMessage :
// *	This method is used to obtains an array of device names that are 
// *	associated with the request.  It is the responsibility of the caller
// *	to delete each element of the array, and the array itself when they
// *	are no longer needed.
// *	This method returns 0 on success, or -1 if the deviceList could 
// *	not be read.
// *****************************************************************************
int cdevMessageBinary::getMessage ( char * & message)
	{
	int result = -1;
	message    = NULL;
	
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_MESSAGE))==0)
		{
		if((result = !reader.get(&message))!=0)
			{
			delete message;
			}		
		}
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getData :
// *	This method is used to read the data cdevData object from the 
// *	binary stream.
// *	This method returns 0 on success, or -1 if the data item could 
// *	not be read.
// *****************************************************************************
int cdevMessageBinary::getData ( cdevData & data)
	{
	int    result = -1;

	// *********************************************************************
	// * Clear the contents of the context data object.
	// *********************************************************************
	data.remove();
		
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_DATA))==0)
		{
		int   tlen;
		int   tpos;
		char *tbuf;

		tpos = xdr_getpos(reader.xdr());
		reader.get(tlen);
		tbuf = reader.buffer()+xdr_getpos(reader.xdr());
		if(tlen!=0 && tbuf!=NULL) data.xdrImport(tbuf, tlen);
		else result = -1;
		xdr_setpos(reader.xdr(), tpos+XDR_Sizeof((void *)NULL, tlen));	
		}
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getContext :
// *	This method is used to read the context cdevData object from the 
// *	binary stream.
// *	This method returns 0 on success, or -1 if the context could 
// *	not be read.
// *****************************************************************************
int cdevMessageBinary::getContext ( cdevData & context)
	{
	int    result = -1;

	// *********************************************************************
	// * Clear the contents of the context data object.
	// *********************************************************************
	context.remove();
		
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_CONTEXT))==0)
		{
		int   tlen;
		int   tpos;
		char *tbuf;

		tpos = xdr_getpos(reader.xdr());
		reader.get(tlen);
		tbuf = reader.buffer()+xdr_getpos(reader.xdr());
		if(tlen!=0 && tbuf!=NULL) context.xdrImport(tbuf, tlen);
		else result = -1;
		xdr_setpos(reader.xdr(), tpos+XDR_Sizeof((void *)NULL, tlen));
		}
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::getTagMap :
// *	This method is used to read the tagMap cdevData object from the 
// *	binary stream.
// *	This method returns 0 on success, or -1 if the tagMap could not be read.
// *****************************************************************************
int cdevMessageBinary::getTagMap ( cdevData & tagMap)
	{
	int    result = -1;

	// *********************************************************************
	// * Clear the contents of the tagMap data object.
	// *********************************************************************
	tagMap.remove();
		
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);
	
	// *********************************************************************
	// * Reposition the binary structure to point to the correct location
	// * and read the data item.
	// *********************************************************************
	if((result = setBinaryPosition(reader, GOTO_TAGMAP))==0)
		{
		int   tlen;
		int   tpos;
		char *tbuf;

		tpos = xdr_getpos(reader.xdr());
		reader.get(tlen);
		tbuf = reader.buffer()+xdr_getpos(reader.xdr());
		if(tlen!=0 && tbuf!=NULL) tagMap.xdrImport(tbuf, tlen);
		else result = -1;
		xdr_setpos(reader.xdr(), tpos+XDR_Sizeof((void *)NULL, tlen));
		}
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


// *****************************************************************************
// * cdevMessageBinary::get :
// *	This method is used to read the complete contents of the packet.
// *	This method returns 0 on success, or -1 if the deviceList could 
// *	not be read.
// *
// *	Note that all data items allocated by this call become the property of
// *	the caller and must be deleted.  Specifically, the deviceList and
// *	message parameters must be deleted.
// *****************************************************************************
int cdevMessageBinary::get ( short    & clientID, 
			     unsigned & transIndex,
			     unsigned & cancelTransIndex,
			     unsigned & localDataIndex,
			     unsigned & foreignDataIndex,
			     unsigned & operationCode,
			     int      & completionCode,
			     unsigned & deviceCount,
			     char **  & deviceList,
			     char *   & message,
			     cdevData & data,
			     cdevData & context,
			     cdevData & tagMap)
	{
	int      result = -1;
	unsigned packetMap = 0;

	// *********************************************************************
	// * Set all data to a default value.
	// *********************************************************************
	clientID         = -1;
	transIndex       = 0;
	cancelTransIndex = 0;
	localDataIndex   = 0;
	foreignDataIndex = 0;
	operationCode    = 0;
	completionCode   = 0;
	deviceCount      = 0;
	deviceList       = NULL;
	message          = NULL;
	data.remove();
	context.remove();
	tagMap.remove();
		
	// *********************************************************************
	// * Attach the data to the XDR_Reader class so that its components
	// * can be extracted.
	// *********************************************************************
	reader.attachData(binary, binaryLen);

	// *********************************************************************
	// * Set the position to the beginning of the data buffer.
	// *********************************************************************
	xdr_setpos(reader.xdr(), 0);
			
	// *********************************************************************
	// * Clear the packet map prior to reading data from the stream.
	// *********************************************************************
	map.rawData       = 0;
	
	// *********************************************************************
	// * Read the packet map from the stream.  This object contains a bit
	// * field that identifies the version of the packet and tells what 
	// * other components are embedded in the binary stream.
	// *********************************************************************
	if((result = !reader.get(packetMap))==0)
		{
		int2map(map, packetMap);
		}
	
	// *********************************************************************
	// * Before processing anything else, the method must ensure that this
	// * packet is of the correct version.  Version 1 for this object.
	// *
	// * Note that reading each field is contingent on the prior fields 
	// * being read correctly.
	// *********************************************************************
	if(!result && map.value.version!=CDEV_PACKET_VERSION) result=-1;
	if(!result && map.value.clientIDSet!=0)  result=!reader.get(clientID);
	if(!result && map.value.transIndexSet!=0) result = !reader.get(transIndex);
	if(!result && map.value.cancelTransIndexSet!=0) result = !reader.get(cancelTransIndex);
	if(!result && map.value.localDataIndexSet!=0) result = !reader.get(localDataIndex);
	if(!result && map.value.foreignDataIndexSet!=0) result = !reader.get(foreignDataIndex);
	if(!result && map.value.operationCodeSet!=0) result = !reader.get(operationCode);
	if(!result && map.value.completionCodeSet!=0) result = !reader.get(completionCode);
	if(!result && map.value.deviceListSet!=0)
		{
		if((result = !reader.get(deviceCount))==0)
			{
			// *********************************************
			// * Allocate and initialize an array sufficient
			// * to hold the contents of the stream.
			// *********************************************
			deviceList = new char * [deviceCount];
			memset(deviceList, 0, sizeof(char *)*deviceCount);

			// *********************************************
			// * Read the individual strings into the array.
			// * Note that the XDR_Reader will automatically
			// * allocate data if the pointers are set to 
			// * NULL.
			// *********************************************
			for(int i=0; i<deviceCount && !result; i++)
				result = !reader.get(&deviceList[i]);
			}
		}
	if(!result && map.value.messageSet!=0) result = !reader.get(&message);

	// *********************************************************************
	// * This mechanism will bypass the standard XDR extractor and allow
	// * the caller to directly read the data from the stream without
	// * performing an additional memory allocation.
	// *********************************************************************
	int   tlen;
	int   tpos;
	char *tbuf;

	if(!result && map.value.dataSet!=0)
		{
		tpos = xdr_getpos(reader.xdr());
		reader.get(tlen);
		tbuf = reader.buffer()+xdr_getpos(reader.xdr());
		if(tlen!=0 && tbuf!=NULL) data.xdrImport(tbuf, tlen);
		else result = -1;
		xdr_setpos(reader.xdr(), tpos+XDR_Sizeof((void *)NULL, tlen));
		}
	if(!result && map.value.contextSet) 
		{
		tpos = xdr_getpos(reader.xdr());
		reader.get(tlen);
		tbuf = reader.buffer()+xdr_getpos(reader.xdr());
		if(tlen!=0 && tbuf!=NULL) context.xdrImport(tbuf, tlen);
		else result = -1;
		xdr_setpos(reader.xdr(), tpos+XDR_Sizeof((void *)NULL, tlen));
		}
	if(!result && map.value.tagMapSet) 
		{
		tpos = xdr_getpos(reader.xdr());
		reader.get(tlen);
		tbuf = reader.buffer()+xdr_getpos(reader.xdr());
		if(tlen!=0 && tbuf!=NULL) tagMap.xdrImport(tbuf, tlen);
		else result = -1;
		xdr_setpos(reader.xdr(), tpos+XDR_Sizeof((void *)NULL, tlen));
		}

	// *****************************************************
	// * In event that a failure occurred after the buffers
	// * was allocated.  Walk through the array and free
	// * each data item... then free the array.
	// *****************************************************
	if(result!=0)
		{
		if(deviceList!=NULL)
			{
			for(int i=0; i<deviceCount; i++)
				{
				if(deviceList[i]!=NULL) delete deviceList[i];
				}
			delete deviceList;
			deviceList = NULL;
			}
		if(message!=NULL) 
			{
			delete message;
			message = NULL;
			}
		clientID         = -1;
		transIndex       = 0;
		localDataIndex   = 0;
		foreignDataIndex = 0;
		operationCode    = 0;
		completionCode   = 0;
		deviceCount      = 0;
		data.remove();
		context.remove();
		tagMap.remove();
		}
	
	// *********************************************************************
	// * Detach the binary buffer from the XDR_Reader to prevent it from 
	// * being deleted when the XDR_Reader class is destroyed.
	// *********************************************************************
	reader.detachData();
	
	return result;
	}


