#define MULTICAST

#include <stdio.h>
#include <sys/types.h>
#ifdef LINUX
#include <linux/socket.h>
#else
#include <socket.h> 
#endif
#include <net/if.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include<sys/time.h>
int read_timeo(int fd, int usec);
main(int argc,char ** argv )
{
#ifdef LYNXOS  
 u_char TTL=224;
#else
 const int TTL=224;
#endif
  char buffer[4096];
  char str[4096];
#ifdef LYNXOS  
  u_char v_off=0, v_on=1;
#else
  const int v_off=0, v_on=1;
#endif
  struct sockaddr_in to;
  struct sockaddr_in from;
  struct ip_mreq multiaddr;
  int m, lost=0;
  long addr;
  char c_addr[16];
  int sock = socket(AF_INET, SOCK_DGRAM, 0);
  int sock_snd = socket(AF_INET, SOCK_DGRAM, 0);
#ifdef LYNXOS
  addr=inet_addr( argv[1]);
  multiaddr.imr_multiaddr.s_addr =htonl(addr);
#else
  inet_pton(AF_INET, argv[1], &addr);
  printf("address=0x%x\n", addr);
  multiaddr.imr_multiaddr.s_addr =addr;
#endif
  multiaddr.imr_interface.s_addr = htonl(INADDR_ANY);
  setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multiaddr, 
	     sizeof(multiaddr));
  setsockopt(sock_snd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &multiaddr, 
	     sizeof(multiaddr));
  if(  setsockopt(sock, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof(TTL)))
    perror("MULTICAST_TTL rcv");
  if(setsockopt(sock_snd, IPPROTO_IP, IP_MULTICAST_TTL, &TTL, sizeof(TTL)))
    perror("MULTICAST_TTL snd");
  
  from.sin_family=AF_INET;
#ifdef LYNXOS
  from.sin_addr.s_addr=htonl(addr); 
#else
  from.sin_addr.s_addr=addr;
#endif
  from.sin_port=htons(12345);
#ifdef LYNXOS
 sprintf(c_addr, inet_ntoa(from.sin_addr));
#else
  inet_ntop(AF_INET, &from.sin_addr.s_addr, &c_addr, 16);
#endif
 if( setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &v_off, 
		sizeof(v_off)) <0)
   perror("IP_MULTICAST_LOOP");
 if( setsockopt(sock_snd, IPPROTO_IP, IP_MULTICAST_LOOP, &v_off, 
		sizeof(v_off)) <0)
   perror("IP_MULTICAST_LOOP");

  memcpy(&to, &from, sizeof(from));

  if (bind(sock, (struct sockaddr *)&from, sizeof(struct sockaddr_in)) < 0)
  {
    perror("multircv: bind failed: ");
    exit(1);
  } 


  for (; ; )
    {
      int chars;
      int len =  sizeof(from);
      str[1] = 'a';
      if(read_timeo(sock, 5000) == 0)
	{
	  printf(".");
	  lost++;
	}
      if((chars= recvfrom(sock, buffer, 4096, 0, 
			 (struct sockaddr *)&from, &len))== -1)
	{
	  perror("rcvfrom failed");
	  exit(1);
	}
      //            printf("buffer[0] %d buffer[1] %c\n",buffer[0],buffer[1] );
      if (buffer[1] != 'a')
	{
	  /*	  if (buffer[0] % 100 == 0)printf("%s\n",
			     inet_ntoa((struct in_addr)to.sin_addr));
	  */
	  // printf("%d\n",(int) buffer[0]);
	  str[0] = buffer[0];
	  str[1] = 'a';
	  if (sendto(sock_snd, str, chars, 0, (struct sockaddr *)&to, len) < 0)
	    perror("sendto");
	  //       printf("sending to %s\n",inet_ntoa((struct in_addr)to.sin_addr)); 
	} //answer if not received an answer
    }
  close(sock);
  close(sock_snd);
}





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));
} 
