CIGI API Version 2.7.1 
CIGI API : Users' Guide
Using the API : User Definable Packets

User Definable Packets

User definable data packets provide a way to send any type of data within in a CIGI message. Refer to one of the following sections for more information.

Packet Field Descriptions

The opcode (packet ID) is stored in the packet_id field of the CIGI_USER_DATA_PACKET. Valid packet IDs for user definable packets fall within the range of numbers defined by CIGI_USER_DATA_PACKET_OPCODE_MIN and CIGI_USER_DATA_PACKET_OPCODE_MAX. Any of these numbers may be used to identify the type data contained within the user definable packet.

The CIGI API CIGI_USER_DATA_PACKET structure definition contains a data_ptr field, which is of type unsigned char *. This field is used to point to the user definable data, and is an exception to the rule, because it does not directly represent the packet as defined in the CIGI specification. Please refer to the CIGI ICD document listed in the references section.

The data_ptr should be set to point to the address of where the user definable data begins. The length of the data is determined by the packet_size field in the CIGI_USER_DATA_PACKET structure, as in the following diagram.

Figure : CIGI User Definable Packet Structure

In the preceeding example, the data_ptr field points to the user definable data, but the data is not part of the CIGI_USER_DATA_PACKET structure itself. The packet_size field is set to 44 bytes in this example, which is computed in the following way.

Total size = CIGI_USER_DATA_PACKET_BASE_SIZE + user data + padding
Total size = 2 + 40 + 2
Total size = 44 bytes

The size of the user data however, may be of any size assuming that the resulting packet will fit into an outgoing message buffer.

API Support for User Definable Packets

The CIGI API will set the data pointer, compute the packet size, and ensure that the opcode to set for the packet is valid. The function for setting the data in a user definable packet is prototyped as follows.

/* Sets the data for a user definable packet */ int CigiSetUserDefinablePacket( CIGI_USER_DATA_PACKET *userPacket, const int opcode, unsigned char *data, const int length );

The CIGI_USER_DATA_PACKET parameter is the address of the packet to set. The opcode parameter is the packet ID to set for the packet, and should be a valid packet ID for user definable packets. The data parameter is the starting address of the user definable data to set for the packet, and the length parameter indicates the total size of the data to add.

When finished using the user definable data packet (after it is added to the outgoing message buffer), the application should notify the API that it is finished using the packet, by calling the CigiClearUserDefinablePacket function, which has the following prototype.

/* Clears the data in a user definable packet */ int CigiClearUserDefinablePacket(CIGI_USER_DATA_PACKET *userPacket);

The userPacket parameter is the address of the packet to clear.

Sending User Definable Packets

User definable packets are added to the outgoing message buffer in the same way that other packets are added, and is done using the following function.

/* Adds a user definable packet to the outgoing message */ int CigiAddPacketUserData( const int sessionid, const CIGI_USER_DATA_PACKET* packet );

This function will copy the packet, including the user data which it points to, to the outgoing message buffer. The layout of the data in the message buffer will be in CIGI format, where the data immediately follows the packet_id and packet_size values. In other words, the value of the data_ptr field is discarded and the data which it points to is added to the buffer.

The function returns a status code, and may fail if the total packet size is too large or if there is not enough room in the outgoing buffer to add it. If the packet size exceeds the outgoing buffer size set when the session is created, this function will fail. In general, the data used for user definable packets should be kept to a minimal size.

Example : Adding a User Definable Packet to an Outoing Message
CIGI_USER_DATA_PACKET userPacket = CigiCreateUserDataPacket(); SOME_USER_DEFINED_DATA_STRUCTURE userData; /* Set the fields in the userData structure... */ ... /* Start a new outgoing message */ CigiStartMessage( session_id); ... /* Set the data in the CIGI_USER_DATA_PACKET to the contents of * the userData structure */ CigiSetUserDefinablePacket( &userPacket, SOME_USER_DEFINED_DATA_OPCODE, ( unsigned char*)&userData, SOME_USER_DEFINED_DATA__SIZE ); ... /* Add the packet to the outgoing message */ CigiAddPacketUserData( session_id, &userPacket); ... /* Clear the user definable packet data */ CigiClearUserDefinablePacket( &userPacket); ... /* End the outgoing message */ CigiEndMessage( session_id);

Note: It is important to note that the application is responsible for managing the actual data which the user definable packet points to. Thus, the memory location which the data_ptr points to should still be valid when the packet is added. If it is allocated dynamically, it should not be deleted (freed) until the packet is added to the outgoing buffer. If it points to another address, the data at that address should still be in scope when the packet is added to the outgoing buffer.

Receiving User Definable Packets

When user definable packets are received in an incoming messasge, they are formatted as specified by the CIGI interface, and not as the CIGI API packet structure definition. The format of the packet within the incoming buffer is illustrated in the following diagram.

Figure : Incoming User Definable Packet

When the incoming message is processed and a user definable packet is encountered, the user definable data will be located at an offset of CIGI_USER_DATA_PACKET_BASE_SIZE bytes from the starting address of the packet. This is illustrated in the following example.

Example : Accessing User Defined Data in an Incoming Message
int opcode = CIGI_OPCODE_NONE; /* The current packet in the incoming message */ char *packet = NULL; ... opcode = CigiGetNextPacket(sessionId, &packet); /* Check for user definable packets */ if( ( opcode >= CIGI_USER_DATA_PACKET_OPCODE_MIN) && ( opcode <= CIGI_USER_DATA_PACKET_OPCODE_MAX)) { CIGI_USER_DATA_PACKET* userPacket = ( CIGI_USER_DATA_PACKET*)packet; int packet_id = userPacket->packet_id; int packet_size = userPacket->packet_id; /* Determine which user definable packet was received and handle * it appropriately */ switch( packet_id) { ... case( SOME_USER_DEFINED_OPCODE): { /* Assume the data is represented by a C structure in this * example, but it can be of any desired. */ SOME_USER_DEFINED_DATA_STRUCTURE *userData = NULL; /* Point to the actual user definable data in the packet */ userData = ( CIGI_USER_PACKET_1*)( packet + CIGI_USER_DATA_PACKET_BASE_SIZE); /* Process the user definable packet... */ ... break; } ... } } ...

The preceeding example encouters a user definable packet in the incoming message buffer, determines the packet ID, and handles it. It finds the position in the buffer where the user definable data starts, and type casts the address to a pointer of the appropriate type, in this case a SOME_USER_DEFINED_DATA_STRUCTURE pointer. Any padding that may appear at the end of the packet is ignored.

Byte-Swapping for User Definable Packets

Normally, byte-swapping is handled transparently by the CIGI API when a packet is added to the outgoing message buffer or when an incoming message buffer is received, and depneding on the presence of the LITTLE_ENDIAN preprocessor definition. For more information refer to the section on preprocessor definitions.

User definable packets however, are not byte swapped by the API and must be performed manually by the application (if needed). Byte swapping will be necessary if the platform is little endian. It should be performed when the LITTLE_ENDIAN preprocessor definition is defined.

To help byte swap the data, the following swap functions can be used. They are named CigiSwapN, where N is the number of bytes to be swapped.

/* Swaps the bytes at a given address */ void CigiSwap2(void *dest, const void *src); void CigiSwap4(void *dest, const void *src); void CigiSwap8(void *dest, const void *src);

In addition, the following macro definitions may be used to simply copy the bytes (ones which do not need to be swapped) from a source to a destination. The copy functions have the same general naming scheme of CigiCopyN, where N is the number of bytes to be copied.

/* Copies bytes from one address to another */ CigiCopy1(_dest_,_src_) /* macro definition omitted */ CigiCopy2(_dest_,_src_) /* macro definition omitted */ CigiCopy4(_dest_,_src_) /* macro definition omitted */ CigiCopy8(_dest_,_src_) /* macro definition omitted */

The following exampe illustrates how to write a byte swapping function for a data structure named USER_PACKET_1.

Example : Byte Swapping User Data
/* Definition of a structure containing user data * for use with a CIGI user definable packet */ typedef struct USER_PACKET_1 { unsigned char packet_size; /* = 24 bytes */ unsigned char val_1; unsigned short val_2; unsigned int val_3; float val_4; float val_5; double val_6; }; /* Byte swapping function for the USER_PACKET_1 type */ int SwapPacketUser1( const USER_PACKET_1* packet, char* dest) { char* src = ( char*)packet; /* packet size : 1 byte */ /* value 1 : 1 byte */ CigiCopy2( dest, src); /* value 2 : 2 bytes */ CigiSwap2( dest + 2, src + 2); /* value 3 : 4 bytes */ CigiSwap4( dest + 4, src + 4); /* value 4 : 4 bytes */ CigiSwap4( dest + 8, src + 8); /* value 5 : 4 bytes */ CigiSwap4( dest + 12, src + 12); /* value 6 : 8 bytes */ CigiSwap8( dest + 16, src + 16); return( CIGI_SUCCESS); }
SourceForge LogoBoeing
******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ******** ********