Libraries
network_udp_polling/main.c
// ////////////////////////////////////////////////////////////////////////////
//
// Sample program sends and receives four packets via two UDP sockets in two
// different threads using the ReceivePacketFromSocketDevice polling function
// to recieve the packets. Program also uses RegisterPrintMessage,
// CreateUnicastUDPSocketDevice, RegisterReceivePacket, StartLoggingMessages,
// and SendPacketFromUDPSocketDevice 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"
#ifdef __linux__
#include <unistd.h>
#include <pthread.h>
#else
#include <windows.h>
#include <process.h>
#endif
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;
boolean_type udp_thread_exit;
// ////////////////////////////////////////////////////////////////////////////
//
// PrintTheMessage controls how messages are processed and displayed to
// the user.
//
// ////////////////////////////////////////////////////////////////////////////
void PrintTheMessage(message_struct_type *mess_struct_ptr)
{
if (mess_struct_ptr->category == MSG_CAT_INFO ||
mess_struct_ptr->category == MSG_CAT_INFO_ALERT ||
mess_struct_ptr->category == MSG_CAT_ERROR ||
mess_struct_ptr->category == MSG_CAT_ERROR_ALERT)
{
printf("%s\t%s\n",GetMessageCategoryAsString(mess_struct_ptr->category),
mess_struct_ptr->message);
}
}
// ////////////////////////////////////////////////////////////////////////////
//
// CreateDataPackets creates the data packets with a three byte header.
// The first three header bytes contains a sync hex pattern = fafbfc.
// The fourth and fifth header bytes contain the overall packet length in big
// endian byte order.
//
// ////////////////////////////////////////////////////////////////////////////
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 char sync_pattern[3];
unsigned short big_endian_order = 1;
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 a five byte header for all the packets. The header is populated
// with the sync bytes and a big endian two byte overall packet length.
// Populate packet data zone
strcpy((char *)packet1_ptr+5,"Mary had a little lamb");
strcpy((char *)packet2_ptr+5,"Its feet were black as soot");
strcpy((char *)packet3_ptr+5,"And into Mary's bread and jam ");
strcpy((char *)packet4_ptr+5,"Its sooty foot it put");
// Get packet length including 5 byte header and null terminator.
*length1_ptr = strlen((char *)packet1_ptr+5) + 6;
*length2_ptr = strlen((char *)packet2_ptr+5) + 6;
*length3_ptr = strlen((char *)packet3_ptr+5) + 6;
*length4_ptr = strlen((char *)packet4_ptr+5) + 6;
// Populate headers.
// Populate packet length field.
if (big_endian_order == 1)
{
memmove(packet1_ptr+3,length1_ptr,2);
memmove(packet2_ptr+3,length2_ptr,2);
memmove(packet3_ptr+3,length3_ptr,2);
memmove(packet4_ptr+3,length4_ptr,2);
}
else
{
memmove(packet1_ptr+4,length1_ptr,1);
memmove(packet2_ptr+4,length2_ptr,1);
memmove(packet3_ptr+4,length3_ptr,1);
memmove(packet4_ptr+4,length4_ptr,1);
}
// Populate sync field.
sync_pattern[0] = 0xfa;
sync_pattern[1] = 0xfb;
sync_pattern[2] = 0xfc;
memcpy(packet1_ptr,sync_pattern,3);
memcpy(packet2_ptr,sync_pattern,3);
memcpy(packet3_ptr,sync_pattern,3);
memcpy(packet4_ptr,sync_pattern,3);
}
// ////////////////////////////////////////////////////////////////////////////
//
// PrintAvailableIPAddesses uses the PopulateIPAddressStructArray function to
// identify and print the host's available IPv4 and IPv6 addresses.
//
// ////////////////////////////////////////////////////////////////////////////
void PrintAvailableIPAddesses()
{
unsigned int number_of_ip_address_structs;
ip_address_struct_type *ip_address_struct_array_ptr = NULL;
ip_address_struct_type ip_address_struct;
unsigned int i;
PopulateIPAddressStructArray(&number_of_ip_address_structs,
&ip_address_struct_array_ptr);
printf("\nIP Addresses:\n\n");
for (i=0; i<number_of_ip_address_structs; i++)
{
ip_address_struct = ip_address_struct_array_ptr[i];
if (ip_address_struct_array_ptr[i].ip_address_version == IPV4)
{
printf("IPv4 address: %s\n",
ip_address_struct_array_ptr[i].ip_address);
}
else
{
switch (ip_address_struct_array_ptr[i].ip_address_v6_category)
{
printf("IPv6 address: %s\tIPv6 category: GLOBAL_FIXED\n",
ip_address_struct_array_ptr[i].ip_address);
break;
printf("IPv6 address: %s\tIPv6 category: GLOBAL_TEMPORARY\n",
ip_address_struct_array_ptr[i].ip_address);
break;
case LINK_LOCAL:
printf("IPv6 address: %s\tIPv6 category: LINK_LOCAL\n",
ip_address_struct_array_ptr[i].ip_address);
break;
printf("IPv6 address: %s\tIPv6 category: TAREDO_TUNNELING\n",
ip_address_struct_array_ptr[i].ip_address);
break;
printf("IPv6 address: %s\tIPv6 category: IPV6_TO_IPV4_TUNNELING\n",
ip_address_struct_array_ptr[i].ip_address);
break;
case MULTICAST:
printf("IPv6 address: %s\tIPv6 category: MULTICAST\n",
ip_address_struct_array_ptr[i].ip_address);
break;
case OTHER:
printf("IPv6 address: %s\tIPv6 category: OTHER\n",
ip_address_struct_array_ptr[i].ip_address);
break;
default:
printf("IPv6 address: %s\tIPv6 category: UNDEFINED_IP_ADDRESS_V6_CATEGORY\n",
ip_address_struct_array_ptr[i].ip_address);
break;
}
}
}
// NOTE: Problems may develop when freeing the memory associated
// with the ip_address_struct_array_ptr if the DS library's compiler
// or run time environment does not match the application code's
// compiler or run time environment. This method is provided to
// avoid those problems. The code, "free(ip_address_struct_array_ptr)"
// will work if the library and application code's compilers
// are the same.
FreeIPAddressStructArrayMemoryAlloc(ip_address_struct_array_ptr);
}
// ////////////////////////////////////////////////////////////////////////////
//
// UdpThread function creates a UDP socket to receive and send packets.
// The function uses the ReceivePacketFromSocketDevice polling function
// to recieve the packets.
//
// ////////////////////////////////////////////////////////////////////////////
#ifdef WIN32
unsigned __stdcall UdpThread(void *arg)
#else
void *UdpThread(void *arg)
#endif
{
char ip_address[50];
unsigned short port;
unsigned short receive_port;
unsigned int queue_size;
unsigned int buffer_size;
char device_key[50];
unsigned int key_buffer_size;
unsigned int receive_timeout; // in milli seconds
unsigned int packet_buffer_size;
int packet_length;
unsigned char packet_buffer[50];
unsigned int message_code;
unsigned int recieve_from_ip_address_buffer_size;
char received_from_ip_address[50];
unsigned short recieved_from_port;
void *return_val = NULL;
int return_code;
// Create a UDP socket device
strcpy(ip_address,"127.0.0.1"); // Use loopback address.
port = 20240;
// Associate a receive queue with the socket so a UDP packet may be
// queued and not dropped if the main thread sends a packet prior
// to UdpThread calling ReceivePacketFromSocketDevice.
queue_size = 10;
buffer_size = 50;
key_buffer_size = sizeof(device_key);
port,
queue_size,
buffer_size,
&key_buffer_size,
device_key) != SUCCESS)
{
#ifdef WIN32
return FAIL;
#else
return(return_val);
#endif
}
// Wait up to 2 seconds to receive the first packet from the main thread.
receive_timeout = 2000;
packet_buffer_size = 50;
recieve_from_ip_address_buffer_size = 50;
// Receive and print first packet.
receive_timeout,
&packet_buffer_size,
&packet_length,
packet_buffer,
&message_code,
&recieve_from_ip_address_buffer_size,
received_from_ip_address,
&recieved_from_port) != SUCCESS)
{
printf("Error\tFailed to receive first packet in UdpThread.\n");
#ifdef WIN32
return FAIL;
#else
return(return_val);
#endif
}
// Print the data zone packet.
printf("Data\t%s\n",(char *)packet_buffer + 5);
// Sleep 1 second to support main thread execution
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
// Send the second packet.
receive_port = 20230;
length2,
packet2,
ip_address,
receive_port) != SUCCESS)
{
printf("Error\tFailed to send second packet in UdpThread.\n");
#ifdef WIN32
return FAIL;
#else
return(return_val);
#endif
}
// Wait up to 2 seconds to receive the third packet from the main thread.
// Receive and print third packet.
receive_timeout,
&packet_buffer_size,
&packet_length,
packet_buffer,
&message_code,
&recieve_from_ip_address_buffer_size,
received_from_ip_address,
&recieved_from_port) != SUCCESS)
{
printf("Error\tFailed to receive third packet in UdpThread.\n");
#ifdef WIN32
return FAIL;
#else
return(return_val);
#endif
}
// Print the data zone packet.
printf("Data\t%s\n",(char *)packet_buffer + 5);
// Send the fourth packet.
length4,
packet4,
ip_address,
receive_port) != SUCCESS)
{
printf("Error\tFailed to send fourth packet in UdpThread.\n");
#ifdef WIN32
return FAIL;
#else
return(return_val);
#endif
}
// Continue to poll the socket for incoming packets until main thread
// sets the udp_thread_exit flag
receive_timeout = 100;
while (udp_thread_exit != TRUE_OR_YES)
{
// Wait up 100 millisec to receive additional packet from the main
// thread.However, no additional packets are being sent from the
// main thread so ReceivePacketFromSocketDevice will timeout with
// error code = DS_TIMEOUT.
if ( (return_code = ReceivePacketFromSocketDevice( device_key,
receive_timeout,
&packet_buffer_size,
&packet_length,
packet_buffer,
&message_code,
&recieve_from_ip_address_buffer_size,
received_from_ip_address,
&recieved_from_port)) == SUCCESS)
{
printf("Data\t%s\n",(char *)packet_buffer + 5);
}
if (return_code == DS_TIMEOUT)
printf("Info\tDS_TIMEOUT.\n");
}
printf("Info\tExiting UdpThread.\n");
#ifdef WIN32
return SUCCESS;
#else
return(return_val);
#endif
}
// ////////////////////////////////////////////////////////////////////////////
//
// Sample program sends and receives four packets via two UDP sockets in two
// different threads using the ReceivePacketFromSocketDevice polling function
// to recieve the packets. Program also uses RegisterPrintMessage,
// CreateUnicastUDPSocketDevice, RegisterReceivePacket, StartLoggingMessages,
// and SendPacketFromUDPSocketDevice API functions.
//
// ////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
char ip_address[50];
unsigned short port;
unsigned short receive_port;
unsigned int queue_size;
unsigned int buffer_size;
char device_key[50];
unsigned int key_buffer_size;
unsigned int receive_timeout; // in milli seconds
unsigned int packet_buffer_size;
int packet_length;
unsigned char packet_buffer[50];
unsigned int message_code;
char log_path[256];
char log_filename[256];
unsigned int recieve_from_ip_address_buffer_size;
char received_from_ip_address[50];
unsigned short recieved_from_port;
#ifdef WIN32
HANDLE d_thread_handle;
unsigned d_thread_id;
#else
pthread_t d_thread_id;
#endif
udp_thread_exit = FALSE_OR_NO;
// Example code using the PopulateIPAddressStructArray function to print
// the host's available ip addresses.
PrintAvailableIPAddesses();
// Create data packets.
CreateDataPackets(packet1,
packet2,
packet3,
packet4,
&length1,
&length2,
&length3,
&length4);
// Register the PrintMessage callback function prior to InitToolkitCfdp
// to process error messages that may be generated during initialization.
RegisterMessage(&PrintTheMessage);
printf("\nNetwork UDP Polling\n\n");
// Create a log file in the home/<username> or Users/<username> directory
// by passing a empty string for directory path. Only log error and
// information messages.
strcpy(log_path,"");
strcpy(log_filename,"network_udp_polling_log_file");
log_filename,
// Create a thread that sends and receives packets
#ifdef __linux__
if (pthread_create(&d_thread_id, NULL, UdpThread,NULL) != 0)
{
printf("Error\tFailed to create UdpThread.\n");
return 0;
}
#else
// Create thread
d_thread_handle = (HANDLE)_beginthreadex(NULL,0,&UdpThread,NULL,0,
&d_thread_id);
if (d_thread_handle == NULL)
{
printf("Error\tFailed to create UdpThread.\n");
return 0;
}
#endif
// Sleep 1 second to allow thread creation to complete
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
// Create a UDP source socket device.
strcpy(ip_address,"127.0.0.1"); // Use loopback address.
port = 20230;
// Associate a receive queue with the socket so a UDP packet may be
// queued and not dropped if the UdpThread sends a packet prior
// to main calling ReceivePacketFromSocketDevice
queue_size = 10;
buffer_size = 50;
key_buffer_size = sizeof(device_key);
port,
queue_size,
buffer_size,
&key_buffer_size,
device_key) != SUCCESS)
{
return 0;
}
// Send the first packet to the UDP thread.
receive_port = 20240;
length1,
packet1,
ip_address,
receive_port) != SUCCESS)
{
printf("Error\tFailed to send first packet in main thread.\n");
udp_thread_exit = TRUE_OR_YES;
return 0;
}
// Wait up to 2 seconds to receive the second packet from the UDP thread.
receive_timeout = 2000;
packet_buffer_size = 50;
recieve_from_ip_address_buffer_size = 50;
// Receive and print second packet.
receive_timeout,
&packet_buffer_size,
&packet_length,
packet_buffer,
&message_code,
&recieve_from_ip_address_buffer_size,
received_from_ip_address,
&recieved_from_port) != SUCCESS)
{
printf("Error\tFailed to receive second packet in main thread.\n");
udp_thread_exit = TRUE_OR_YES;
return 0;
}
// Print the data zone packet.
printf("Data\t%s\n",(char *)packet_buffer + 5);
// Send the third packet to the UDP thread.
length3,
packet3,
ip_address,
receive_port) != SUCCESS)
{
printf("Error\tFailed to send third packet in main thread.\n");
udp_thread_exit = TRUE_OR_YES;
return 0;
}
// Wait up to 2 seconds to receive the fourth packet from the UDPthread.
// Receive and print fourth packet.
receive_timeout,
&packet_buffer_size,
&packet_length,
packet_buffer,
&message_code,
&recieve_from_ip_address_buffer_size,
received_from_ip_address,
&recieved_from_port) != SUCCESS)
{
printf("Error\tFailed to receive fourth packet in main thread.\n");
udp_thread_exit = TRUE_OR_YES;
return 0;
}
// Print the data zone packet.
printf("Data\t%s\n",(char *)packet_buffer + 5);
// Allow time to print messages.
#ifdef __linux__
sleep(1);
#else
Sleep(1000);
#endif
// Exit UdpThread
udp_thread_exit = TRUE_OR_YES;
return 0;
}