Libraries
cfdp_destination/main.c
// ////////////////////////////////////////////////////////////////////////////
//
// Example program receives and processes CFDP transaction requests.
// This program must be launched prior to the execution of any of
// CFDP example programs.
//
// ////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "trek_error.h"
#include <sys/timeb.h>
#include <string.h>
unsigned int message_mask;
// ////////////////////////////////////////////////////////////////////////////
//
// PrintTheMessage controls how messages are processed and displayed to
// the user.
//
// ////////////////////////////////////////////////////////////////////////////
void PrintTheMessage(message_struct_type *mess_struct_ptr)
{
if (mess_struct_ptr->category & message_mask)
{
printf("%s%s\n",GetMessageCategoryAsPaddedString(mess_struct_ptr->category),
mess_struct_ptr->message);
}
}
// ////////////////////////////////////////////////////////////////////////////
//
// DeviceData's packet_buffer_ptr processes a cfdp_struct ptr defined as
// follows:
//
// char source_pathname[200];
// char destination_pathname[200];
// long long eid; (destination)
// char transaction_id[50];
// unsigned short percent_transferred;
// unsigned long bytes_transferred;
// unsigned long file_size;
// unsigned long cfdp_configuration; (e.g., DS_DEVICE_SENDING,
// DS_DEVICE_RECEIVING)
// unsigned long cfdp_status; (e.g., DS_PACKET_SENDING,
// DS_PACKET_RECEIVING,
// DS_SUSPEND, DS_RESUME,
// DS_REPORT,
// DS_CANCEL,
// DS_SUCCESS,
// DS_FAIL,
// DS_ABANDON,
// DS_UNKNOWN)
//
// The cfdp_struct can be used to determine each file's transactions ID as
// well as monitor a file's transfer status.
//
// ////////////////////////////////////////////////////////////////////////////
void DeviceData(const char *device_key,
int packet_length,
unsigned char *packet_buffer_ptr)
{
unsigned int count;
cfdp_struct_type *cfdp_struct_ptr;
// Retrieve the individual cfdp structs from the packet_buffer;
for (count = 0; count*sizeof(cfdp_struct_type) < (unsigned int)packet_length; count++)
{
cfdp_struct_ptr = (cfdp_struct_type *)(packet_buffer_ptr + count*sizeof(cfdp_struct_type));
if (cfdp_struct_ptr->cfdp_status == DS_MESSAGE)
{
// Print user message
printf("Message %s\n",cfdp_struct_ptr->message);
}
else if (message_mask & MSG_CAT_PROGRESS)
{
printf("Progress Transaction_id %s -> %s\t file size=%lld\t bytes trans=%lld\t percent trans=%u%%\n",
cfdp_struct_ptr->transaction_id,
cfdp_struct_ptr->destination_pathname,
cfdp_struct_ptr->file_size,
cfdp_struct_ptr->bytes_transferred,
cfdp_struct_ptr->percent_transferred);
}
}
}
// ////////////////////////////////////////////////////////////////////////////
//
// CreateDataFile creates a binary file with the specified pathname and size.
//
// ////////////////////////////////////////////////////////////////////////////
int CreateDataFile(char *pathname,
unsigned int file_size)
{
FILE *file_ptr = NULL;
char fill_data[250];
unsigned int i;
if ((file_ptr = fopen(pathname,"wb")) == NULL)
{
printf("Error Failed to open example data file.\n");
return(FAIL);
}
// Write to data file //
memset(fill_data,0xfe,sizeof(fill_data));
for (i = 0; i < file_size; i+=sizeof(fill_data))
fwrite(fill_data,1,sizeof(fill_data),file_ptr);
fflush(file_ptr);
fclose(file_ptr);
return(SUCCESS);
}
// ////////////////////////////////////////////////////////////////////////////
//
// InitExampleDataFiles creates 1MB, 2MB and 3MB example data files and returns
// the appropriate source and destination pathnames.
//
// ////////////////////////////////////////////////////////////////////////////
int InitExampleDataFiles(char *pathname1MB,
char *destination_pathname1MB,
char *pathname2MB,
char *destination_pathname2MB,
char *pathname3MB,
char *destination_pathname3MB)
{
struct timeb timebuffer;
char home_path[256];
if (TCAACGetHomeDirectory(home_path,sizeof(home_path)) != SUCCESS)
{
return(FAIL);
}
// Create a 1MB example data file
sprintf(pathname1MB, "%s/cfdp_destination_data_file_1MB",home_path);
if (CreateDataFile(pathname1MB,1000000) == FAIL)
{
return(FAIL);
}
// Create a destination time tag appended file name
ftime(&timebuffer);
sprintf(destination_pathname1MB,"%s_%u",
pathname1MB,
(unsigned int)timebuffer.time);
// Create a 2MB example data file
sprintf(pathname2MB, "%s/cfdp_destination_data_file_2MB",home_path);
if (CreateDataFile(pathname2MB,2000000) == FAIL)
{
return(FAIL);
}
// Create a destination time tag appended file name
sprintf(destination_pathname2MB,"%s_%u",
pathname2MB,
(unsigned int)timebuffer.time);
// Create a 3MB example data file
sprintf(pathname3MB, "%s/cfdp_destination_data_file_3MB",home_path);
if (CreateDataFile(pathname3MB,3000000) == FAIL)
{
return(FAIL);
}
// Create a destination time tag appended file name
sprintf(destination_pathname3MB,"%s_%u",
pathname3MB,
(unsigned int)timebuffer.time);
return(SUCCESS);
}
// ////////////////////////////////////////////////////////////////////////////
//
// Main with optional input defining pathname for the CFDP configuration file.
// The default CFDP configuration file pathname is
// "./cfdp_destination_config.txt".
//
// Sample program receives and processes CFDP transactions. To exit simply
// enter "exit", "e", "quit", or "q".
//
// This program must be launched prior to the execution of any of
// CFDP example programs.
//
// ////////////////////////////////////////////////////////////////////////////
int main(int argc, char *argv[])
{
char pathname[256];
unsigned short exit_flag = 0;
char arg1[50];
char log_path[256];
char log_filename[256];
char pathname1MB[256];
char destination_pathname1MB[256];
char pathname2MB[256];
char destination_pathname2MB[256];
char pathname3MB[256];
char destination_pathname3MB[256];
memset(arg1,0x00,50);
// Intialize message mask to print error messages.
message_mask = MSG_CAT_ERROR;
// Set default CFDP config_pathname
strcpy (pathname, "./cfdp_destination_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 CFDP initialization
RegisterMessage(&PrintTheMessage);
// Initialize CFDP. This funcition creates, connects and configures the
// socket and CFDP library
if (InitToolkitCfdp(pathname) == SUCCESS)
{
// Must initialize toolkit CFDP prior to recording CFDP metrics
strcpy(log_path,"");
strcpy(log_filename,"cfdp_destination_metrics_file.csv");
StartRecordingCFDPMetricsSnapshot(log_path,log_filename);
if (GetDisplayMessageMask(&message_mask) != SUCCESS)
{
printf("Error Failed to GetDisplayMessageMask.\n");
}
// Register the CFDPDeviceData callback function after initialization
// since the CFDPDevice does not exist prior to initialization and this
// function would fail.
if (RegisterCFDPDeviceData(&DeviceData) != SUCCESS)
{
printf("Error Failed to RegisterCFDPDeviceData.\n");
}
// Create 1MB, 2MB and 3MB example data files.
if (InitExampleDataFiles(pathname1MB,
destination_pathname1MB,
pathname2MB,
destination_pathname2MB,
pathname3MB,
destination_pathname3MB) != SUCCESS)
{
printf("Error Failed to InitExampleDataFiles.\n");
return 0;
}
printf("\nCFDP Destination\n\n");
printf("To exit application enter: \"e\" or \"q\" or \"exit\" or \"quit\".\n");
while (exit_flag == 0)
{
fgets(arg1, 50, stdin);
arg1[strlen(arg1)-1] = '\0';
if (strcmp(arg1,"exit") == 0 || strcmp(arg1,"quit") == 0 ||
strcmp(arg1,"e") == 0 || strcmp(arg1,"q") == 0)
{
exit_flag = 1;
}
else
{
printf("To exit application enter: \"e\" or \"q\" or \"exit\" or \"quit\".\n");
}
}
}
// Remove orginal data files (if they still exist).
remove(pathname1MB);
remove(pathname2MB);
remove(pathname3MB);
return 0;
}