/*
 * Socket.c
 *
 *  Created on: 17. Mai 2017
 *      Author: PirklbauerMa
 */

/* ========================================================================== */
/*                            Includes		                                  */
/* ========================================================================== */
#include <xdc/std.h>
#include <xdc/runtime/System.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/ndk/inc/bsd/sys/socket.h>
#include "ti/ndk/inc/bsd/socketndk.h"


// The following header should not be included referring to the NDK Reference Guide
// No header of the ti/ndk/inc should be included
/*
#include "ti/ndk/inc/socketndk.h"
#include "ti/ndk//inc/os/osif.h"
#include "ti/ndk/inc/usertype.h"
*/


/* ========================================================================== */
/*                            Constructors	                                  */
/* ========================================================================== */

void EchoTcpClient( IPN IPAddrLocal, IPN IPAddrExt )
{
	SOCKET s = INVALID_SOCKET;
	struct sockaddr_in sinExt;
	struct sockaddr_in sinLocal;
	int i, received, sent, error, val, buffersize ,ret = 0;
	char *pBuf = 0;
	char *pBufTest = 0;
	struct timeval timeout;

	buffersize = 2048;

	System_printf("\n== Start TCP Echo Client Test ==\n");

	// Allocate the file descriptor environment for this Task
	ret = fdOpenSession( (HANDLE)Task_self() );
	if (ret = 0){
		System_printf("failed to create file descriptor session!");
		goto leave;
	}
	else if (ret = 1) { System_printf("= File Descriptor session opened successfully =\n");}
	// Create test socket
	s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);	// returns a file descriptor representing the socket
	if( s == INVALID_SOCKET ){ // INVALID_SOCKET stands for -1
		System_printf("failed socket create (%d)\n",fdError());
		goto leave;
	}
	else{ System_printf("= Socket created successfully =\n");}
	// Prepare address for connect
	bzero( &sinExt, sizeof(struct sockaddr_in) );
	sinExt.sin_family = AF_INET;
	sinExt.sin_addr.s_addr = IPAddrExt;	// Var.2 to set IP Addr. PC
	sinExt.sin_port = htons(54217); // Port PC
	//inet_aton("192.168.1.10", &sinExt.sin_addr.s_addr); // Var.1 to set IP Addr. PC

	// Configure our Tx and Rx timeout to be 5 seconds
	timeout.tv_sec = 5;
	timeout.tv_usec = 0;
	// Set send timeout
	ret = setsockopt( s, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof( timeout ) );
	if (ret < 0 ){
		System_printf("failed set socket option (%d)\n",fdError());
		goto leave;
	}
	else if (ret = 0) { System_printf("= Socket Option set successfully =\n");}
	// Set receive timeout
	ret = setsockopt( s, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof( timeout ) );
	if (ret < 0 ){
		System_printf("failed set socket option (%d)\n",fdError());
		goto leave;
	}
	else if (ret = 0) { System_printf("= Socket Option set successfully =\n");}
	// Connect socket - &sinExt is the pointer to the serv_addr
	ret = connect( s , (PSA) &sinExt, sizeof(sinExt));
	if( ret < 0 ){
		error = fdError();
		System_printf("\nfailed connect (%d)\n", error);
		goto leave;
	}
	else if (ret = 0) { System_printf("= Socket connected successfully =\n");}
	// Allocate a working buffer and testing buffer
	if( !(pBuf = malloc( buffersize )) )
	{
		System_printf("failed buffer allocation\n");
		goto leave;
	}
	if( !(pBufTest = malloc( buffersize )) )
	{
		System_printf("failed test buffer allocation\n");
		goto leave;
	}
	// Fill buffer with a test pattern
	for(i=0; i<buffersize; i++)
	{
		*(pBuf+i) = (char)i;
	}
	//
	// Send the buffer - return is the amount of successfully sent bytes
	sent = send( s, pBuf, buffersize, 0 );
	if( ret < 0 )
	{
		System_printf("send failed (%d)\n",fdError());
		goto leave;
	}
	// Try and receive the test pattern back - returns the number of bytes received .. data is in Buffer in pBufTest
	received = recv( s, pBufTest, buffersize, MSG_WAITALL );
	if( received < 0 )
	{
		System_printf("recv failed (%d)\n",fdError());
		goto leave;
	}
	// Verify reception size and pattern
	if( sent != received )
	{
		System_printf("received %d (not %d) bytes\n",received, sent);
		goto leave;
	}
	for(i=0; i<buffersize; i++)
		if( *(pBufTest+i) != (char)i )
		{
			System_printf("verify failed at byte %d\n",i);
			break;
		}
	// If here, the test passed
	if( received==sent )
		System_printf("passed\n");

leave:
	if( pBuf )
		free( pBuf );
	if( pBufTest )
		free( pBufTest );
	if( s != INVALID_SOCKET )
		fdClose( s );
	System_printf("== End TCP Echo Client Test ==\n\n");

	// Free the file descriptor environment for this Task
	fdCloseSession( (HANDLE)Task_self() );

}


