Demo entry 2950409

appLayer.c

   

Submitted by anonymous on Nov 04, 2015 at 23:17
Language: C. Code size: 15.3 kB.

#include "appLayer.h"

#define FILE_NAME   1
#define FILE_SIZE   0
#define C_DATA      '0'
#define C_START     '1'
#define C_END       '2'


// checks the type and number of arguments and sets the application mode, according to the arguments
int checkArguments(int argc, unsigned char* argv[]){
    // check the number of arguments
    if(argc!=3 && argc!=4)
        return FALSE;

    // check the serial port number
    int portNumber = atoi(argv[1]);
    if(portNumber!=0 && portNumber!=1 && portNumber!=2 && portNumber!=3 && portNumber!=4 && portNumber!=5) 
        return FALSE; 
    
    // check the mode
    if(strcmp("transmitter",argv[2]) == 0)
        app.mode=TRANSMITTER;
    else if(strcmp("receiver",argv[2]) == 0)
        app.mode=RECEIVER;
    else return FALSE;

    // set demonstration mode
    if(argc==4 && strcmp("demonstration",argv[3]) == 0)
        linkProtocol.demonstrationMode=TRUE;
    else linkProtocol.demonstrationMode=FALSE;

    return TRUE;
}

// prompts the user to enter the name of a file to transfer
void openFile(){
    unsigned char fileName[MAX_LENGTH];
    
    clearScreen();
    printf("|| File Transfer Application\n");
    printf("||||||||||||||||||||||||||||||||||||\n");
    printf(" file/. || ");
        
    scanf("%s", fileName);

    app.fdFile = open(fileName, O_RDONLY);

    if(app.fdFile < 0){ 
        printf("|| (!) Error: File not found.\n");
        exit(-1);
    }else strcpy(app.fileName,fileName);
}

// creates a file
int createFile(){
    app.fdFile = open(app.fileName, O_CREAT | O_WRONLY | O_TRUNC, 0666);
    
    if(app.fdFile < 0) 
        return FALSE;
    
    return TRUE;
}

// initiates statistics of data link
void startStatistics(){
    linkStatistics.transmissions=0;  
    linkStatistics.timeOuts=0;
    linkStatistics.nREJs=0;
}

// displays statistics about a transfer
void displayStatistics(){
    clearScreen();
    printf("|| Transfer overview...\n");
    printf("||||||||||||||||||||||||||||||||||||\n");

    if(app.mode==TRANSMITTER){
        printf("||%d I frames transmited.\n", linkStatistics.transmissions);  
        printf("||%d timeouts occurred.\n", linkStatistics.timeOuts);
        printf("||%d REJs received.\n", linkStatistics.nREJs);
    }else{
        printf("||%d I frames received.\n", linkStatistics.transmissions);  
        printf("||%d REJs sent.\n", linkStatistics.nREJs);
    }
}

// cleans the screen for easier reading.
void clearScreen(){
    if(fork() == 0){
        // clear the screen
        execlp("clear","clear",NULL);  
        exit(-1);
    }     

    // wait for screen to be cleaned
    int state;
    wait(&state);
}

// prompts the user to configure the application's settings
int userSettings() {
    unsigned char BAUDRATES[10][20]= {"B300","B1200","B4800","B9600", "B14400", "B19200", "B28800", "B38400 (default)", "B57600", "B115200"};
    
    // default settings
    int baudrate = 7, iFrameMaxSize = 90, nTransmissions = 3, timeout = 3;
    
    do{
        unsigned char input[STRING_LENGTH];

        clearScreen();
        printf("|| User settings...\n");
        printf("|| Select Baudrate\n");
        printf("||||||||||||||||||||||||||||||||||||\n");
        
        int i;      
        for (i=0; i < 10; i++)
            printf(" %d || %s\n",i,BAUDRATES[i]);

        printf(" option/. || ");

        scanf("%s",input);

        if(strcmp(input,".")==0)
            return FALSE;

        baudrate = atoi(input);
        if(baudrate <= 9 && baudrate >= 0)
            break;      
    }while(TRUE);
    
    if (app.mode == TRANSMITTER)
    do{
        unsigned char input[STRING_LENGTH];

        clearScreen();
        printf("|| User settings...\n");
        printf("|| Enter I-Frames maximum size\n");
        printf("||||||||||||||||||||||||||||||||||||\n");
        printf(" (100-250)/. || ");

        scanf("%s",input);

        if(strcmp(input,".")==0)
            return FALSE;

        iFrameMaxSize = atoi(input);
        if(iFrameMaxSize >= 100 && iFrameMaxSize <=250)
            break;      
    }while(TRUE);

    do{
        unsigned char input[STRING_LENGTH];

        clearScreen();
        printf("|| User settings...\n");
        printf("|| Enter timeout limit\n");
        printf("||||||||||||||||||||||||||||||||||||\n");
        printf(" (1-180)/. || ");

        scanf("%s",input);

        if(strcmp(input,".")==0)
            return FALSE;

        timeout = atoi(input);
        if(timeout >= 1 && timeout <= 180)
            break;      
    }while(TRUE);

    do{
        unsigned char input[STRING_LENGTH];

        clearScreen();
        printf("|| User settings...\n");
        printf("|| Retry limit\n");
        printf("||||||||||||||||||||||||||||||||||||\n");
        printf(" (1-50)/. || ");

        scanf("%s",input);

        if(strcmp(input,".")==0)
            return FALSE;

        nTransmissions = atoi(input);
        if(nTransmissions >= 1 && nTransmissions <=50)
            break;      
    }while(TRUE);
    
    // save settings
    setUserProtocol(baudrate,timeout,nTransmissions);
    app.frameSize = iFrameMaxSize;

    printf("|| (!) User configurations set\n");

    return TRUE;
}

// prompts the user to choose between configuring the application's settings or use the default configuration
int settings(){
    do{
        unsigned char input;

        clearScreen();
        printf("|| File Transfer Application...\n");
        printf("|| Use default settings ? \n");
        printf("||||||||||||||||||||||||||||||||||||\n");
        printf(" y/n/. || ");
    
        scanf("%c",&input);

        if(input=='.')
            break;

        if(input == 'y'){
            app.frameSize = 100;        // default I-Frame size
            setUserSettings(FALSE);
            return TRUE;
        }else if(input == 'n') {
            return userSettings();
        }
    }while(TRUE);

    return FALSE;
}

// generates information about the file's size in format TLV
int getSizeInfo(unsigned char* sizeInfo){   
    // check the size of the file
    struct stat fileStatistics;
    if(fstat(app.fdFile,&fileStatistics)<0)
        return FALSE;
    
    app.fileSize = fileStatistics.st_size;
    unsigned char fileSize[STRING_LENGTH];
    sprintf(fileSize,"%d",app.fileSize);

    // prepare size TLV information
    sprintf(sizeInfo,"%x%x%s",FILE_SIZE,(unsigned int)strlen(fileSize),fileSize);
    return TRUE;
}

// generates information about the file's name in format TLV
int getNameInfo(unsigned char* nameInfo){
    // prepare name TLV information
    sprintf(nameInfo,"%x%c%s",FILE_NAME,(unsigned int)strlen(app.fileName),app.fileName);
    return TRUE;
}

// prepares a control command of the specified type
int makeControlCommand(int type, unsigned char* command){
    unsigned char nameInfo[STRING_LENGTH], sizeInfo[STRING_LENGTH];
    
    if(getSizeInfo(sizeInfo) == FALSE || getNameInfo(nameInfo) == FALSE)
        return FALSE;

    sprintf(command,"%c%s%s", type, sizeInfo, nameInfo);
    return TRUE;
}

// prepares an I-Frame with sequenceNumber with data from buf
void prepareData(unsigned char* buf, unsigned char* data, int sequenceNumber, int size){
    data[0] = C_DATA;
    data[1] = (unsigned char) sequenceNumber;
    data[2] = (unsigned char) ((unsigned short) size >> 8);
    data[3] = (unsigned char) size;

    int n;
    for (n=4; n < size + 4; n++) 
        data[n] = buf[n-4];
}

// starts the application in TRANSMITTER mode, prompts the user to specify a file to be transferred 
void startTransmitter(){

    openFile(app.fileName); // prompt the user to open the file to transfer

    // prepare control commands
    unsigned char start[STRING_LENGTH], end[STRING_LENGTH];
    if(makeControlCommand(C_START, start) == FALSE || makeControlCommand(C_END, end)==FALSE){
        close(app.fdFile);
        return;
    }

    // initiate transfer statistics
    startStatistics();

    // send start command
    if(llwrite(app.fdSerialPort,start,strlen(start))<0){
        close(app.fdFile);
        return;
    }       

    // read file and send data in packets
    unsigned char data[MAX_LENGTH];
    unsigned char buf[MAX_LENGTH];
    int sequenceNumber = 0;
    int bytesRead, bytesSent = 0;
    int success=TRUE;
    
    while((bytesRead = read(app.fdFile, buf, app.frameSize)) > 0){
        // display progress information
        clearScreen();      
        printf("|| (%%) Transfering '%s'...\n%d %% \n",app.fileName, (int) (bytesSent * 100)/ app.fileSize);

        // prepare data packet
        prepareData(buf, data, sequenceNumber, bytesRead);

        // send data packet
        if(llwrite(app.fdSerialPort, data, bytesRead+4) < 0){
            success=FALSE;
            break;      
        }
        
        bytesSent+=bytesRead;
        sequenceNumber = (++sequenceNumber) % 255;
    }
    
    // send end command
    if(llwrite(app.fdSerialPort,end,strlen(end))<0)
        success=FALSE;

    if(llclose(app.fdSerialPort)!=0)
        printf("|| (!) Error closing the connection.\n");

    // display completion message
    transferComplete(success, TRUE);

    // close file
    close(app.fdFile);
    return;
}

void transferComplete(int fileChecked, int fileCreated){
    // display transfer confirmation
    
    displayStatistics();

    if(fileChecked==TRUE)
        printf("|| (!) Transfer of '%s' completed successfully.\n",app.fileName);
    else printf("|| (!) Transfer of '%s' completed with errors.\n",app.fileName);

    if(fileCreated==FALSE)
        printf("|| (!) Error: File '%s' could not be created.\n",app.fileName);


    printf("|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\n");

}

// checks if the information on startCommand matches the information of endCommand and if the file created has the supposed size
int checkFile(unsigned char* startCommand, unsigned char* endCommand) {

    startCommand[0] = endCommand[0];
    
    if (strcmp(startCommand, endCommand)) {
        printf("|| (!) Error in startCMD or endCMD...\n");
        return FALSE;
    }

    // check the size of the file
    struct stat fileStatistics;
    if (fstat(app.fdFile,&fileStatistics) < 0) {
        printf("|| (!) FSTAT returned error...\n");
        return FALSE;
    }
    
    // check if the file size matches the expected
    if (app.fileSize != fileStatistics.st_size) {
        printf("|| (!) File size not as expected...\n");
        return FALSE;
    }
    
    return TRUE;

}

// reads from the given command the information about the file's size
int parseFileSize(unsigned char* command){

    unsigned char fileSizeTemp[2];
    fileSizeTemp[0]=command[2];
    fileSizeTemp[1]='\0';
    int fileSizeLength = (int) strtol(fileSizeTemp, NULL, 16);
    unsigned char fileSize[STRING_LENGTH];

    int n;  
    for (n=3; n < 3 + fileSizeLength; n++)
        fileSize[n-3] = command[n];
    
    fileSize[fileSizeLength] = '\0';
    app.fileSize = atoi(fileSize);

    return n;
}

// reads from the given command the information about the file's name
void parseFileName(unsigned char* command, int index){

    int nameLength = (int) command[index++];

    unsigned char fileName[STRING_LENGTH];
    int n;
    for (n=0; n < nameLength; n++)
        fileName[n] = command[index + n];
    
    fileName[nameLength]= '\0';
    strcpy(app.fileName,fileName);
}

// reads from the given command the information about the file's size and name and saves a copy of the command
void parseControlCommand(unsigned char* command, int commandLength, unsigned char* commandCopy){

    parseFileName(command, parseFileSize(command)+1);
    
    int n;
    for(n=0; n<commandLength; n++)
        commandCopy[n]=command[n];
}

// retrieves information from the given buffer storing it on data buffer
int parseData(unsigned char* buf, int bufLength, unsigned char* data){
    
    // check if buf size is as expected
    unsigned short expectedSize = 0;
    expectedSize = ((buf[2] | expectedSize) << 8) | buf[3];

    if((int) expectedSize != bufLength - 4)
        return -1;

    int n;
    for (n=4; n < bufLength; n++)
        data[n-4] =buf[n];

    // return the sequence number
    return (int) buf[1];
}

// starts the application in RECEIVER mode.
// Once the transfer is complete, displays a success message or a message error.
void startReceiver(){

    // initiate transfer statistics
    startStatistics();

    // control commands and data buffers
    unsigned char data[MAX_LENGTH], start[STRING_LENGTH], end[STRING_LENGTH];
    unsigned char readBuf[MAX_LENGTH];
    int sequenceNumber = 0;
    int bytesRead, bytesReceived = 0;
    int fileCreated = TRUE, fileChecked = FALSE, endOfFile=FALSE;

    app.fileSize=1;

    // read data packets
    while((bytesRead = llread(app.fdSerialPort,readBuf)) >= 0){

        // display progress information
        clearScreen();
        printf("|| (%%) Transfering...\n%d %% \n", (int) ((bytesReceived* 100)/ app.fileSize));

        switch(readBuf[0]){
            case C_START:
                parseControlCommand(readBuf, bytesRead, start);
                fileCreated = createFile();
                break;

            case C_END:
                parseControlCommand(readBuf, bytesRead, end);
                fileChecked = checkFile(start, end);
                endOfFile=TRUE;
                
                break;
            case C_DATA: 
                bytesReceived+=(bytesRead-4);

                if(parseData(readBuf,bytesRead,data) == sequenceNumber){                
                    write(app.fdFile, data, bytesRead - 4);
                    sequenceNumber = (++sequenceNumber) % 255;
                }else printf("|| (!) Invalid data received\n");
                
                break;
            default:
                break;
        }
        
        if(endOfFile)
            break;
    }

    if(llclose(linkProtocol.fd)!=0)
        printf("|| (!) Error closing the connection\n");

    // display transfer confirmation
    transferComplete(fileChecked, fileCreated);

    close(app.fdFile);
    return;
}

int main(int argc, unsigned char* argv[]){
    // check arguments
    if(checkArguments(argc,argv)==FALSE){
        printf("(!) Usage: %s <port> <device>\n", argv[0]);
        printf("(!) Alternative usage: %s <port> <device> <mode>\n", argv[0]);
        exit(1);
    }

    logfd = fopen("log.txt", "w");

    // prompt the user to use default settings or choose other configuration
    if(settings()==FALSE)
        return -1;

    // setup connection
    app.fdSerialPort = llopen(atoi(argv[1]), app.mode);
    if(app.fdSerialPort<0)
        exit(1);

    // start application
    if(app.mode == TRANSMITTER)
        startTransmitter();
    else if(app.mode == RECEIVER)
        startReceiver();

    return 0;
}

This snippet took 0.03 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).