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.
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.
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.
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;
...
CigiStartMessage( session_id);
...
CigiSetUserDefinablePacket(
&userPacket,
SOME_USER_DEFINED_DATA_OPCODE,
( unsigned char *)&userData,
SOME_USER_DEFINED_DATA__SIZE
);
...
CigiAddPacketUserData( session_id, &userPacket);
...
CigiClearUserDefinablePacket( &userPacket);
...
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;
char *packet = NULL;
...
opcode = CigiGetNextPacket(sessionId, &packet);
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;
switch ( packet_id)
{
...
case ( SOME_USER_DEFINED_OPCODE):
{
SOME_USER_DEFINED_DATA_STRUCTURE *userData = NULL;
userData = ( CIGI_USER_PACKET_1*)(
packet + CIGI_USER_DATA_PACKET_BASE_SIZE);
...
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.
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.
CigiCopy1(_dest_,_src_)
CigiCopy2(_dest_,_src_)
CigiCopy4(_dest_,_src_)
CigiCopy8(_dest_,_src_)
|
|
|
The following exampe illustrates how to write a byte swapping function for a data structure named
USER_PACKET_1.
Example : Byte Swapping User Data |
typedef struct USER_PACKET_1
{
unsigned char packet_size;
unsigned char val_1;
unsigned short val_2;
unsigned int val_3;
float val_4;
float val_5;
double val_6;
};
int SwapPacketUser1( const USER_PACKET_1* packet, char * dest)
{
char * src = ( char *)packet;
CigiCopy2( dest, src);
CigiSwap2( dest + 2, src + 2);
CigiSwap4( dest + 4, src + 4);
CigiSwap4( dest + 8, src + 8);
CigiSwap4( dest + 12, src + 12);
CigiSwap8( dest + 16, src + 16);
return ( CIGI_SUCCESS);
}
|
|
|
|
|