/*****************************************************************************/
/* Simple TCP server                                                         */
/*                                                                           */
/* The server get no input as external parameters                            */
/*                                                                           */
/*                                                                           */
/*                                                                           */
/* Process:                                                                  */
/*   The server binds the requested port                                     */
/*   Listen to conenction requests from clients (multiple clientsi supported)*/
/*   Accepts conneciton from client                                          */
/*                                                                           */
/* Termination:                                                              */
/*   Close the connection as needed                                          */
/*                                                                           */
/*                                                                           */
/*                                                                           */
/* The source is taken from Beej's Guide to Network Programming              */
/*                                                                           */
/*                                                                           */
/*                                                                           */
/*****************************************************************************/



    #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> 

    #define MYPORT 3490    			/* the port users will be connecting to */

    #define BACKLOG 10     		/* how many pending connections queue will hold */

    int main()
    {
        int sockfd, new_fd;  /* listen on sock_fd, new connection on new_fd 	*/
        struct sockaddr_in my_addr;    	/* my address information 		*/
        struct sockaddr_in their_addr; 	/* connector's address information 	*/
        struct sockaddr_in sock_addr; 	/* connector's address information 	*/
        struct sockaddr_in peer_addr; 	/* connector's address information 	*/
        int    sin_size;		/*					*/ 
	int    len;			/* Size of sockaddr			*/

        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
            perror("socket");
            exit(1);
        }

        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 */

	/*Binding the requested port */	
        if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \
                                                                      == -1) {
            perror("bind");
            exit(1);
        }

	/*Listent to the incoming conenction request from the client */
        if (listen(sockfd, BACKLOG) == -1) {
            perror("listen");
            exit(1);
        }

        while(1) {  /* main accept() loop */
            sin_size = sizeof(struct sockaddr_in);
            if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, \
                                                          &sin_size)) == -1) {
                perror("accept");
                continue;
            }
            printf("server: got connection from %s\n", \
                                               inet_ntoa(their_addr.sin_addr));
	/********************************************************************************/
	/*Important : The server recieves multiple connection in the same program 	*/
	/*but only answers are forked 							*/
	/********************************************************************************/
            if (!fork()) { /* this is the child process */
	
	    	len = sizeof(sock_addr);	    
                if (getsockname(new_fd, (struct sockaddr *)&sock_addr, &len ) == -1){
                    perror("getsockname");
                    close(new_fd);
                    return(-1);
		}
		printf("sockname: sock_addr.sin_port=%d \n",ntohs(sock_addr.sin_port)); 
		printf("sockname: sock_addr.sin_family=%d \n",sock_addr.sin_family);
		printf("sockname: sock_addr.sin_addr=%s \n",inet_ntoa(sock_addr.sin_addr));
		
                if (getpeername(new_fd, (struct sockaddr *)&sock_addr, &len ) == -1){
                    perror("getpeername");
                    close(new_fd);
                    return(-1);
		}
		printf("peername: sock_addr.sin_port=%d \n",ntohs(sock_addr.sin_port)); 
		printf("peername: sock_addr.sin_family=%d \n",sock_addr.sin_family);
		printf("peername: sock_addr.sin_addr=%s \n",inet_ntoa(sock_addr.sin_addr));
		
                if (send(new_fd, "Hello, world!\n", 14, 0) == -1)
                    perror("send");
                close(new_fd);
                exit(0);
            }
            close(new_fd);  /* parent doesn't need this */

            while(waitpid(-1,NULL,WNOHANG) > 0); /* clean up child processes */
        }
    }
