/******************************************************** 
 * 
 * File:           bounceUDP.c 
 *
 * P.N.:            
 * 
 * Rel.:           1.0.0 
 *
  * Product:        UDP Latency test for loop controls 
 *
 * Property:       UNINA - All rights reserved 
 *
 * Author:         Fabio Garufi 
 * 
 * Creation Date:  March 16, 2005 
 *
 * Description: 
 * 	Bounches a UDP pachet to its source.
 * 
 * Revisions History: 
 *
 *
 ********************************************************/

/*@****************************************************** 
 *	INCLUDE SECTION
 ********************************************************/
#include <sys/types.h>
#include <fcntl.h>

#ifdef LINUX
#include <linux/socket.h>
#else
#include <socket.h>
#endif
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include<net/if.h>
#include <sys/time.h>
#define NUM_CAR 4096
#define PORT  12345
int read_timeo(int fd, int usec);
/*@******************************************************
 * Function: main 
 * 
 * Description: 
 * 
 * INPUT: 
 * 
 * OUTPUT: 
 *
 * RETURN VALUE: 
 * 
 ********************************************************/ 
main(argc, argv)
int argc;
char **argv;
{
  int s,s1, fd;
  char str_in[NUM_CAR];
  char str_out[NUM_CAR];
  unsigned int dest_ip_addr;
  struct sockaddr_in loc_addr;
  struct sockaddr_in rem_addr;
  struct sockaddr src_addr;
  struct sockaddr sockname;
  struct hostent * loc_host;
  struct hostent     * rem_host;
  int i,j;
  int namelen;
  int num_car_letti;
  int  val;
  struct ifreq testioctl;
  u_short port;
  struct timeval timeo;
  unsigned long        addr_tmp;
  int lost;
 if(argc <3)
    {
      printf("usage %s <local_IP> <rem_IP> [<port>]\n", argv[0]);
      return -1;
    }
  if ((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
	perror("ubeam: socket call failed: ");
	exit(1);
  } /* end if */
  if ((s1 = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
	perror("ubeam: socket call failed: ");
	exit(1);
  } /* end if */
 
 loc_host = gethostbyname(argv[1]);
 rem_host = gethostbyname(argv[2]);
 
  //loc_host = gethostbyaddr(argv[1], strlen(argv[1]), AF_INET);
  if (loc_host == (struct hostent *)NULL) {
    perror("ubeam: error in gethostbyname: ");
    exit(1);
  } /* end if */
  
  loc_addr.sin_family = AF_INET;
/*********************************************/
  if(argc == 4)
    port = (u_short)atoi(argv[3]);
  else
    port = PORT;

  loc_addr.sin_port = htons(port);
  loc_addr.sin_addr.s_addr = INADDR_ANY;

/*********************************************/
  if (bind(s, (struct sockaddr*)&loc_addr, sizeof(struct sockaddr_in)) < 0) {
    printf("errno = %d \n", errno);
	perror("ubeam: bind failed: ");
	exit(1);
  } /* end if */
  rem_addr.sin_port = htons(port+1);
   bcopy(rem_host->h_addr, (char *)&addr_tmp, rem_host->h_length);
  rem_addr.sin_addr.s_addr = addr_tmp;

  for (i=0; i<NUM_CAR; i++) str_out[i] = (i % 10) + '0';
    
  while (1) {
	
        namelen = sizeof(struct sockaddr);
	if(read_timeo(s, 5000) == 0)
	  {
//	    printf(".");
	    lost++;
	  }
        if ((num_car_letti = recvfrom(s, str_in, NUM_CAR, 
                                      0, &src_addr, &namelen)) == -1) {
	    perror("ubeam: recvfrom failed: ");
	    exit(1);
        }

        if (sendto(s1, str_in, num_car_letti, 0, (struct sockaddr*)&rem_addr, 
                   namelen) < 0) {
          perror("ubeam: sendto failed: ");
          exit(1);
        }
//  	    printf(".");
	fflush(stdout); 
  } /* end for */

  close(s);
  close(s1);

} /* end of main */

int read_timeo(int fd, int usec)
{
  fd_set rset;
  struct timeval timeo;
  FD_ZERO(&rset);
  FD_SET(fd, &rset);
  
  timeo.tv_sec=0;
  timeo.tv_usec=usec;

  return(select(fd+1, &rset, NULL, NULL, &timeo));
} 
