#include <stdio.h>
#include <stdlib.h> 
#include <netinet/in.h>
#include <sys/types.h>
#include <netinet/ip.h>
#include <string.h>
#include <sys/socket.h>
#include <netdb.h>  
#include <unistd.h>
#include <time.h>
#include <arpa/inet.h>
#include <math.h>

#define PORT 4992
#define BUFSIZE 1024
#define TCPREADBUF 16384

int recvlen;        // # bytes received 
int tcpbytes = 0;   // # bytes in tcp read buff
int fd;     		// udp socket for discovery
int tcpsoc; 		// tcp socket

unsigned int flexip;// radio's IP Address

unsigned char buf[BUFSIZE];	/* udp receive buffer */
unsigned char tcpinbuf[TCPREADBUF];

void delay(int micro_seconds) {
    
    clock_t start_time = clock();
    while (clock() < start_time + micro_seconds);
}

int main (int argc, const char *argv[])
{
    
    struct sockaddr_in myaddr;		// local  UDP address
    struct sockaddr_in remaddr;     // remote address
    struct sockaddr_in tcpaddr;     // local TCP address
    struct sockaddr_in tcpremaddr;  // radio address
  

    socklen_t addrlen = sizeof(remaddr);  /* length of address */
    
/* ******  Start Discovery ********************************** */

    /* create a UDP socket */
    
    if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
        perror("cannot create socket\n");
        return 0;
    }

    /* bind the UDP socket to any valid IP address and port 4992 */
    
    memset((char *)&myaddr, 0, sizeof(myaddr)); // zero memory that will hold myaddr
    myaddr.sin_family = AF_INET;
    myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    myaddr.sin_port = htons(PORT);
    
    if (bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
        perror("bind failed");
        return 0;
    }

    /* socket blocks until it receives Broadcast Packet from Flex */
    recvlen = recvfrom(fd, buf, BUFSIZE, 0, (struct sockaddr *)&remaddr, &addrlen);
    
    /* 
     * When the UDP socket reads a packet from the Flex, 
     * the struct sockaddr_in, remaddr, gets 
     * populated with the radios ip address and port number
    */

    flexip = remaddr.sin_addr.s_addr;  // Flex ip address in network byte order, big_endian
       
	for (int i = 28; i < recvlen ; i++){
	    
	      if(buf[i] == 0x20) {
			  i++;
			  printf("\n"); }
			  
		  printf("%c", buf[i]);	 
	}
	
	printf("\n \n");

    close(fd);    // close udp socket after first successful read

/* ******  End of Discovery ********************************** */

/* Create TCP Socket */
    
    if ((tcpsoc = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        perror("cannot create socket");
        return 0;
    }
    
    memset((char *)&tcpaddr, 0, sizeof(tcpaddr)); // client sockaddr
    tcpaddr.sin_family = AF_INET;
    tcpaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    tcpaddr.sin_port = htons(0);
    
    memset((char *)&tcpremaddr, 0, sizeof(tcpremaddr)); // radio sockaddr
    tcpremaddr.sin_family = AF_INET;
    tcpremaddr.sin_addr.s_addr = (uint32_t) flexip;
    tcpremaddr.sin_port = htons(PORT); // htons(PORT)

    if (bind(tcpsoc, (struct sockaddr *)&tcpaddr, sizeof(tcpaddr)) < 0) {
        perror("bind failed");
        return 0;
    }
    	
/* connect TCP socket to radio */
    
    if (connect(tcpsoc, (struct sockaddr *)&tcpremaddr, sizeof(tcpremaddr)) < 0) {
        perror("connect failed");
        return 0;
    }
    
    delay(1000000);	// wait 1 sec for buffer to fill
    
    tcpbytes = read(tcpsoc, tcpinbuf, TCPREADBUF);
    
    printf(" ************************* TCP Data ************************ \n");
    
    for (int i = 0; i < tcpbytes; i++){
		printf("%c", tcpinbuf[i]);
	}
    
    close(tcpsoc);
}
