/*********************************************************************/
/* UDP Broadcast listener                                            */    
/*                                                                   */    
/* This program is a UDP server that recieves message sent by        */    
/* Broadcast                                                         */    
/*                                                                   */    
/* Prepared by Eddie Aronovich                                       */    
/*********************************************************************/
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <errno.h> 
    #include <string.h> 
    #include <sys/types.h> 
    #include <netinet/in.h> 
    #include <sys/socket.h> 
    #include <sys/wait.h> 
    #include <sys/time.h> 
    #include <sys/unistd.h> 
    #include <sys/time.h>
    #include <netinet/tcp.h>         /* for TCP_xxx defines */
 

    #define MYPORT 3879    /* the port users will be sending to */

    #define MAXBUFLEN 100
	

    main()
    {
        int 	sockfd;
        int 	addr_len, 	numbytes;
        char 	buf[MAXBUFLEN];
	int	i;
	int	chosen_digit;	
	int	on=1;
	char	chosen_number[5];
        struct 	sockaddr_in 	my_addr;    /* my address information */
        struct 	sockaddr_in 	their_addr; /* connector's address information */

	chosen_number[0] = '\0';
	printf ("Hello world \n");
	for (i=0;i<4;i++){
		chosen_digit=(int) (10.0*rand()/(RAND_MAX+1.0));
		if (index(chosen_number, chosen_digit+48) == 0 ){
			chosen_number[i] = chosen_digit + 48; /*Adding 48 to convert between ASCII char and digit */
			chosen_number[i+1]='\0';
		}
		else
			i--;
	}
	printf("The chosen number by the server is : %s \n", chosen_number);

        if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }
	else
		printf(" \n The socket got sockfd=%d \n ",sockfd);

        my_addr.sin_family = AF_INET;         /* host byte order */
        my_addr.sin_port = htons(MYPORT);     /* short, network byte order */
        my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */
        bzero(&(my_addr.sin_zero), 8);        /* zero the rest of the struct */

        if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) /* The bind command makes the ability to wait for messages */
           == -1) {
            perror("bind");
            exit(1);
        }
while (1){
	printf("Wait for packet \n");
        addr_len = sizeof(struct sockaddr);


        bzero(&(their_addr), 20);        /* zero the rest of the struct */
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { /*Enable reuse of a socket*/
            perror("setsockopt");
            exit(1);
        }
 

	if ((numbytes=recvfrom(sockfd, buf, MAXBUFLEN, 0, \
                            (struct sockaddr *)&their_addr, &addr_len)) == -1) {
                        perror("recvfrom");
                        exit(1);
                }

       	printf("got packet from %s ",inet_ntoa(their_addr.sin_addr));
       	printf("packet is %d bytes long ",numbytes);
       	buf[numbytes] = '\0'; 
       	printf("packet contains \"%s\"\n",buf);

 	if (check_reply(chosen_number, buf, sockfd, their_addr) == -1) {
        	perror("Check reply");
		exit(1);
	} 

        printf("After the recv \n");

        if ((numbytes=sendto(sockfd, buf, strlen(buf), 0, \
             (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
                perror("sendto");
                exit(1);
        }
        else
                printf("sent %d bytes to %s : %s, \n",numbytes,inet_ntoa(their_addr.sin_addr),buf);
}




        close(sockfd);
    }

int check_reply(char chosen_number[],char buf[], int sockfd,  struct sockaddr_in their_addr){

	int	i;	
	int	digits;		/*number of right digit only */
	int	exact;		/*number of right exact digits & location */
	int	find_place;
	int	digit;
	int	numbytes;
	int	on=1;
	char	guess_number[5];
	char	user_id[5];
	char	user_number[5];
	char	one_char_string[2];
	char	reply[5]="nDnE";
	
	

	/*Striping the number that the user tried to guess */
	for (i=0;i<4;i++){
		guess_number[i] = buf[i]; /*copying the user guess to a different variable */
	}
	guess_number[4]='\0';

	/*Striping the user ID */
	for (i=0;i<4;i++){
		user_id[i] = buf[i+5]; /*copying the user ID to a different variable */
	}
	user_id[4]='\0';

	/*Striping the number that the user tried to guess */
	for (i=0;i<4;i++){
		user_number[i] = buf[i+10]; /*copying the user guess to a different variable */
	}
	user_number[4]='\0';

	printf("In the check routine, chosen_number = %s, buf = %s, guess_number=%s, user_id=%s, user_number=%s \n",chosen_number, buf,guess_number, user_id, user_number);

	digits=exact=0;
	one_char_string[1] = '\0';
	
	for (i=0;i<4;i++){

		one_char_string[0] = user_number[i];	
		digit = user_number[i];	
		printf("the tested char is: = %s \t",one_char_string);

		/*find_place = strncmp(chosen_number, one_char_string, 4);*/
		/*find_place = strcmp(chosen_number, one_char_string); */
		(char) find_place = index(chosen_number, digit);
		/*printf("found_place = %c \n", find_place); 		*/
		if (find_place == 0 ){
			printf("this digit was not found \n");
			}
							
		else{
			printf("this digit (digit at offset %d) was found. The finding corresponds ", i);
			if (user_number[i] == chosen_number[i]){
				printf("value & position \n");
				exact++;
			}
			else {
				printf("value only \n");
				digits++;
			}
		}
	}
	printf("digits=%d, exact = %d \n",digits, exact);
	reply[0] = digits + 48;
	reply[2] = exact + 48;
	reply[4] = '\0';
	


        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1) { /*Enable reuse of a socket*/
            perror("setsockopt");
            exit(1);
        }
 

        if ((numbytes=sendto(sockfd, reply, strlen(reply), 0, \
             (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1) {
                perror("sendto");
                exit(1);
        }
        else
                printf("sent %d bytes to %s: %s\n",numbytes,inet_ntoa(their_addr.sin_addr),reply);

        bzero(&(their_addr), 20);        /* zero the rest of the struct */



	return 0;
} 
