TReK ANSI-C  5.3.3
All ANSI-C APIs
record_udp/main.c
// ////////////////////////////////////////////////////////////////////////////
//
// Sample program sends and receives four packets via two UDP sockets and
// records the packets in two different record files. The record library
// device is configured using the record_udp_config.txt file and the
// record_udp_php_config.txt file. The record library device moves all
// closed record files to a simulated CFDP dropbox. Program uses
// RegisterPrintMessage, StartLoggingMessages, StopLoggingMessages,
// InitToolkitRecordDevice, CreateUnicastUDPSocketDevice, CreateDeviceKeyAlias,
// RegisterRecordDeviceData, SendPacketFromUDPSocketDevice,
// CloseAllRecordFiles and DSCleanUp API functions.
//
// ////////////////////////////////////////////////////////////////////////////
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include "ds_shared.h"
#include "trek_error.h"
#include <sys/timeb.h>
#ifdef __linux__
#include <unistd.h>
#else
#include <windows.h>
#endif
// ////////////////////////////////////////////////////////////////////////////
//
// PrintTheMessage controls how messages are processed and displayed to
// the user.
//
// ////////////////////////////////////////////////////////////////////////////
void PrintTheMessage(message_struct_type *mess_struct_ptr)
{
// Do not print the debug messages
if (mess_struct_ptr->category != MSG_CAT_DEBUG)
printf("%s\t%s\n",GetMessageCategoryAsString(mess_struct_ptr->category),
mess_struct_ptr->message);
}
// ////////////////////////////////////////////////////////////////////////////
//
// DeviceData's packet_buffer_ptr processes a record_device_struct ptr
// defined as follows:
//
// unsigned long ds_message_code; (e.g., DS_CLOSE)
// char record_library_device_name[256];
// char record_file_base_name[256];
// char record_path_and_filename[256];
//
// The record_device_struct can be used to determine when the record library
// device closes a record file as well as the new name of the
// record file
//
// ////////////////////////////////////////////////////////////////////////////
void DeviceData(const char *record_library_device_name,
int packet_length,
unsigned char *packet_buffer_ptr)
{
record_device_struct_type *record_device_struct_ptr;
record_device_struct_ptr = (record_device_struct_type *)packet_buffer_ptr;
if (record_device_struct_ptr->ds_message_code == DS_CLOSE)
{
printf("Successfully closed record file with pathname: %s.\n",
record_device_struct_ptr->record_path_and_filename);
}
}
//
// NAME: ByteSwap4Bytes
//
// INPUTS:
//
// OUTPUTS: unsigned char *packet
//
// RETURNS: none
//
// DESCRIPTION:
//
void ByteSwap4Bytes(unsigned char *packet)
{
unsigned char buffer[4];
memmove(buffer, packet, 4);
memmove(packet, &buffer[3], 1);
memmove(packet + 1, &buffer[2], 1);
memmove(packet + 2, &buffer[1], 1);
memmove(packet + 3, &buffer[0], 1);
}
// ////////////////////////////////////////////////////////////////////////////
//
// CreateDataPackets creates four packets with an eight byte header.
// The header is defined in the record_tcp_php_config.txt file.
// Header definition: 2 byte big endian overall packet length
// 4 byte big endian unix time stamp
// 2 byte big endian mille time stamp
//
// ////////////////////////////////////////////////////////////////////////////
void CreateDataPackets(unsigned char *packet1_ptr,
unsigned char *packet2_ptr,
unsigned char *packet3_ptr,
unsigned char *packet4_ptr,
unsigned short *length1_ptr,
unsigned short *length2_ptr,
unsigned short *length3_ptr,
unsigned short *length4_ptr)
{
// Determine if this is a little endian or big endian platform.
unsigned short tester= 1;
unsigned char tester_byte[1];
unsigned short big_endian_order = 1;
struct timeb current_time;
unsigned int tim;
memcpy(tester_byte,&tester,1);
if (tester_byte[0] == 0x01)
{
big_endian_order = 0;
}
// Zero fill the packets prior to populating.
memset(packet1_ptr,0x00,50);
memset(packet2_ptr,0x00,50);
memset(packet3_ptr,0x00,50);
memset(packet4_ptr,0x00,50);
// Create an eight byte header for all the packets. The header is defined
// in the record_tcp_php_config.txt file.
// Header definition: 2 byte big endian overall packet length
// 4 byte big endian unix time stamp
// 2 byte big endian mille time stamp
// Populate the time zone
if (big_endian_order == 1)
{
ftime(&current_time);
tim = (unsigned int)current_time.time;
memmove(packet1_ptr+2, (unsigned char*)&tim,4);
memmove(packet1_ptr+6, (unsigned char*)&current_time.millitm,2);
//
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
ftime(&current_time);
tim = (unsigned int)current_time.time;
memmove(packet2_ptr+2, (unsigned char*)&tim,4);
memmove(packet2_ptr+6, (unsigned char*)&current_time.millitm,2);
//
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
ftime(&current_time);
tim = (unsigned int)current_time.time;
memmove(packet3_ptr+2, (unsigned char*)&tim,4);
memmove(packet3_ptr+6, (unsigned char*)&current_time.millitm,2);
//
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
ftime(&current_time);
tim = (unsigned int)current_time.time;
memmove(packet4_ptr+2,(unsigned char*)&tim,4);
memmove(packet4_ptr+6,(unsigned char*)&current_time.millitm,2);
}
else
{
ftime(&current_time);
tim = (unsigned int)current_time.time;
ByteSwap4Bytes((unsigned char*)&tim);
memmove(packet1_ptr + 2, (unsigned char*)&tim, 4);
memmove(packet1_ptr+6, (unsigned char*)&current_time.millitm+1,1);
memmove(packet1_ptr+7, (unsigned char*)&current_time.millitm,1);
//
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
ftime(&current_time);
tim = (unsigned int)current_time.time;
ByteSwap4Bytes((unsigned char*)&tim);
memmove(packet2_ptr + 2, (unsigned char*)&tim, 4);
memmove(packet2_ptr+6, (unsigned char*)&current_time.millitm+1,1);
memmove(packet2_ptr+7, (unsigned char*)&current_time.millitm,1);
//
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
ftime(&current_time);
tim = (unsigned int)current_time.time;
ByteSwap4Bytes((unsigned char*)&tim);
memmove(packet3_ptr + 2, (unsigned char*)&tim, 4);
memmove(packet3_ptr+6, (unsigned char*)&current_time.millitm+1,1);
memmove(packet3_ptr+7, (unsigned char*)&current_time.millitm,1);
//
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
ftime(&current_time);
tim = (unsigned int)current_time.time;
ByteSwap4Bytes((unsigned char*)&tim);
memmove(packet4_ptr + 2, (unsigned char*)&tim, 4);
memmove(packet4_ptr+6, (unsigned char*)&current_time.millitm+1,1);
memmove(packet4_ptr+7, (unsigned char*)&current_time.millitm,1);
}
// Populate packet data zone
strcpy((char *)packet1_ptr+8,"Mary had a little lamb");
strcpy((char *)packet2_ptr+8,"Its feet were black as soot");
strcpy((char *)packet3_ptr+8,"And into Mary's bread and jam ");
strcpy((char *)packet4_ptr+8,"Its sooty foot it put");
// Get packet length including 5 byte header and null terminator.
*length1_ptr = (unsigned short)strlen(packet1_ptr+8) + 8;
*length2_ptr = (unsigned short)strlen(packet2_ptr+8) + 8;
*length3_ptr = (unsigned short)strlen(packet3_ptr+8) + 8;
*length4_ptr = (unsigned short)strlen(packet4_ptr+8) + 8;
// Populate headers.
// Populate packet length field.
if (big_endian_order == 1)
{
memmove(packet1_ptr,length1_ptr,2);
memmove(packet2_ptr,length2_ptr,2);
memmove(packet3_ptr,length3_ptr,2);
memmove(packet4_ptr,length4_ptr,2);
}
else
{
memmove(packet1_ptr+1,length1_ptr,1);
memmove(packet2_ptr+1,length2_ptr,1);
memmove(packet3_ptr+1,length3_ptr,1);
memmove(packet4_ptr+1,length4_ptr,1);
}
return;
}
// ////////////////////////////////////////////////////////////////////////////
//
// Sample program sends and receives four packets via two UDP sockets and
// records the packets in two different record files. The record library
// device is configured using the record_udp_config.txt file and the
// record_udp_php_config.txt file. The record library device moves all
// closed record files to a simulated CFDP dropbox. Program uses
// RegisterPrintMessage, StartLoggingMessages, StopLoggingMessages,
// InitToolkitRecordDevice, CreateUnicastUDPSocketDevice, CreateDeviceKeyAlias,
// RegisterRecordDeviceData, SendPacketFromUDPSocketDevice,
// CloseAllRecordFiles and DSCleanUp API functions.s.
//
// ////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
char ip_address[50];
unsigned short source_port;
char source1_device_key[50];
char source1_device_name[50];
char source2_device_key[50];
char source2_device_name[50];
unsigned int receive_queue_size;
unsigned int receive_buffer_size;
unsigned char packet1[50];
unsigned char packet2[50];
unsigned char packet3[50];
unsigned char packet4[50];
unsigned short length1;
unsigned short length2;
unsigned short length3;
unsigned short length4;
unsigned int key_buffer_size;
char pathname[256];
// Set default record library config_pathname
strcpy (pathname, "./record_udp_config.txt");
if (argc == 2)
{
strcpy(pathname,argv[1]);
}
else if (argc > 2)
{
printf("Error Command line contains too many arguments.\n");
return 0;
}
// Register the PrintMessage callback function prior to InitToolkitCfdp
// to process error messages that may be generated during initialization.
RegisterMessage(&PrintTheMessage);
printf("\nRecord UDP\n\n");
printf("Create four data packets.\n");
// Create data packets.
CreateDataPackets(packet1,
packet2,
packet3,
packet4,
&length1,
&length2,
&length3,
&length4);
// Initialize the record library device. This funcition creates,
// connects and configures the sockets associated with
// record library
if (InitToolkitRecordDevice(pathname) == SUCCESS)
{
// Create a UDP client 1 source socket device
strcpy(ip_address,"127.0.0.1"); // Use loopback address
source_port = 0;
// A receive queue is not required since this socket is only
// sending packets
receive_queue_size = 0;
receive_buffer_size = 0;
key_buffer_size = sizeof(source1_device_key);
source_port,
receive_queue_size,
receive_buffer_size,
&key_buffer_size,
source1_device_key) != SUCCESS)
{
return 0;
}
// Define a user friendly device name and associate the name with a device
// key. The device name is an alias for the device key and may
// be used in functions requiring a device key. The name must be unique
// for all devices. A device may not have multiple names.
strcpy(source1_device_name,"UDP_client1");
if (CreateDeviceKeyAlias(source1_device_key,
source1_device_name) != SUCCESS)
{
return 0;
}
// Create a udp client 2 source socket device
strcpy(ip_address,"127.0.0.1"); // Use loopback address
source_port = 0;
// A receive queue is not required since this socket is only
// sending packets
receive_queue_size = 0;
receive_buffer_size = 0;
key_buffer_size = sizeof(source2_device_key);
source_port,
receive_queue_size,
receive_buffer_size,
&key_buffer_size,
source2_device_key) != SUCCESS)
{
return 0;
}
// Define a user friendly device name and associate the name with a device
// key. The device name is an alias for the device key and may
// be used in functions requiring a device key. The name must be unique
// for all devices. A device may not have multiple names.
strcpy(source2_device_name,"udp_client2");
if (CreateDeviceKeyAlias(source2_device_key,
source2_device_name) != SUCCESS)
{
return 0;
}
// Associate the DeviceData callback function with the record
// device library. The function will print a message when a
// record file is closed and renamed by the record library device.
if (RegisterRecordDeviceData(&DeviceData) != SUCCESS)
{
return 0;
}
// Send packet packet1 using UDP_client1
if (SendPacketFromUDPSocketDevice(source1_device_name,length1,packet1, ip_address,9100) != SUCCESS)
{
return 0;
}
// Send packet packet2 using UDP_client1
if (SendPacketFromUDPSocketDevice(source1_device_name,length2,packet2, ip_address, 9100) != SUCCESS)
{
return 0;
}
// Send packet packet3 using UDP_client2
if (SendPacketFromUDPSocketDevice(source2_device_name,length3,packet3, ip_address, 9101) != SUCCESS)
{
return 0;
}
// Send packet packet4 using UDP_client2
if (SendPacketFromUDPSocketDevice(source2_device_name,length4,packet4, ip_address, 9101) != SUCCESS)
{
return 0;
}
// Allow time to print and log messages.
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
// Close all record files using record device api
{
printf("Error Closing all record files.\n");
}
}
// Allow time to print and log messages.
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
// Close the log file. A timetag is appended to the log filename.
return 0;
}
Message codes and structure definition for the Device Service library.
#define DS_CLOSE
4 DS message code for Close
Definition: ds_shared.h:29
Structure of parameters needed for message support.
Definition: trek_toolkit_common_api_ansi_c.h:74
char message[MAX_MESSAGE_SIZE]
Message.
Definition: trek_toolkit_common_api_ansi_c.h:77
enum message_category category
Message category (e.g., MSG_CAT_ERROR, MSG_CAT_ERROR_ALERT, MSG_CAT_WARNING, MSG_CAT_WARNING_ALERT,...
Definition: trek_toolkit_common_api_ansi_c.h:76
Structure of parameters needed for record device status.
Definition: ds_shared.h:198
char record_path_and_filename[256]
Path and filename of closed record file.
Definition: ds_shared.h:202
unsigned long ds_message_code
DS message code describing the event (i.e., DS_CLOSE, a record file was closed).
Definition: ds_shared.h:199
An ANSI C Data Service API.
int EXPORT_THIS_TOOLKIT_DS_C_FUNCTION CreateUnicastUDPSocketDevice(const char *ip_address, unsigned short port, unsigned int receive_queue_size, unsigned int receive_buffer_size, unsigned int *device_key_buffer_size_ptr, char *device_key)
Creates a UDP socket to send and receive packets at the specified IP address and port....
Definition: toolkit_ds_api_ansi_c.cpp:126
int EXPORT_THIS_TOOLKIT_DS_C_FUNCTION DSCleanUp()
Initiates a graceful shutdown of the Device Service library and all supporting device libraries,...
Definition: toolkit_ds_api_ansi_c.cpp:3843
int EXPORT_THIS_TOOLKIT_DS_C_FUNCTION SendPacketFromUDPSocketDevice(const char *device_key, int packet_length, unsigned char *packet_buffer_ptr, const char *send_to_ip_address, unsigned short send_to_port)
Sends a packet from UDP socket device to the IP address and port number of a corresponding UDP socket...
Definition: toolkit_ds_api_ansi_c.cpp:1921
int EXPORT_THIS_TOOLKIT_DS_C_FUNCTION StopLoggingMessages()
Stops logging messages to a file, closes the log file and renames the log file by concatenating the l...
Definition: toolkit_ds_api_ansi_c.cpp:3479
int EXPORT_THIS_TOOLKIT_DS_C_FUNCTION RegisterMessage(void(*function_ptr)(message_struct_type *message_struct_ptr))
Register a callback function to receive and process messages issued by the DS library.
Definition: toolkit_ds_api_ansi_c.cpp:3951
int EXPORT_THIS_TOOLKIT_DS_C_FUNCTION CreateDeviceKeyAlias(const char *device_key, const char *device_key_alias)
Create a user friendly name/alias and associate it with a device key.
Definition: toolkit_ds_api_ansi_c.cpp:910
Error codes for the DS API (starts at 50001)
An ANSI C record device API.
int EXPORT_THIS_TOOLKIT_RECORD_DEVICE_C_FUNCTION CloseAllRecordFiles()
CloseAllRecordFiles closes all the currently open record files in the record library device....
Definition: toolkit_record_device_api_ansi_c.cpp:731
int EXPORT_THIS_TOOLKIT_RECORD_DEVICE_C_FUNCTION InitToolkitRecordDevice(const char *config_pathname)
Intializes the Record Device library using parameters read from a configuration file.
Definition: toolkit_record_device_api_ansi_c.cpp:110
int EXPORT_THIS_TOOLKIT_RECORD_DEVICE_C_FUNCTION RegisterRecordDeviceData(void(*function_ptr)(const char *record_library_device_name, int packet_length, unsigned char *packet))
Register a callback function to receive receive record_devcie_struct status messages including the na...
Definition: toolkit_record_device_api_ansi_c.cpp:852
Command codes for TReK.
#define SUCCESS
The function completed successfully.
Definition: trek_error.h:8
The commonly shared macros, structures and functions.
@ MSG_CAT_DEBUG
Debug message.
Definition: trek_toolkit_common_api_ansi_c.h:63
const char EXPORT_THIS_TREK_TOOLKIT_COMMON_API_FUNCTION * GetMessageCategoryAsString(enum message_category input)
Converts an enumerated message category value into its equivalent character string.
Definition: trek_toolkit_common_api_ansi_c.cpp:45