/*
 * main(): This function is the entry point for the server program of Share Your Playlist application.
 * This function creates the upload and download sockets and waits for client connections.
 * We have implemented all the 3 methods used in concurrency in servers namely:
 * 1. Multi-process approach using fork() for handling upload and download functionalities
 * 2. Non-blocking I/O using select() for monitoring two ports on server
 * 3. Multi-threaded approach for data redundancy between servers
 */
int main(int argc, char **argv) {
	struct sockaddr_in sockserv;
	unsigned int alen;
	int upload_sock, download_sock, i, slave_sock, fds[2], *fd = NULL;
	struct sockaddr *addr;
	socklen_t *addrlen;

	//binds sockets for upload and download functionality
	upload_sock = passiveTCP(UPLOAD_PORT);
	download_sock = passiveTCP(DOWNLOAD_PORT);

	printf("Upload sock : %d\n", upload_sock);
	printf("Download sock : %d\n", download_sock);

	fds[0] = upload_sock;
	fds[1] = download_sock;

	while (1) {
		//calls function to identify which port client connected to
		slave_sock = network_accept_any(fds, 2, &fd);

		//Initializing thread attributes for prstats thread
		(void) pthread_attr_init(&ta);
		(void) pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
		(void) pthread_mutex_init(&stats.st_mutex, 0);

		/*if(pthread_create(&th, &ta, (void * (*)(void *))prstats, 0) < 0)
		 fatal("prstats thread failed");*/

		//Based on socket that obtained the connection, we use multi-process approach using fork() to provide concurrency
		//Based on upload/download, the respective functions are called in the child processes.
		if (*fd == upload_sock) {
			switch (fork()) {
			case 0:
				close(*fd);
				exit(handleUpload(slave_sock));
			default:
				close(slave_sock);
				break;
			}
		}
		if (*fd == download_sock) {
			switch (fork()) {
			case 0:
				close(*fd);
				exit(handleDownload(slave_sock));
			default:
				close(slave_sock);
				break;
			}
		}
	}
}
Exemple #2
0
/*------------------------------------------------------------------------
 * main - Concurrent TCP server for browse_file_system service
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
    char    *service = get_port();  /* service name or port number  */
    struct  sockaddr_in fsin;       /* the address of a client      */
    int     alen;                   /* length of client's address   */
    int     msock;                  /* master server socket         */
    int     ssock;                  /* slave server socket          */

    switch (argc)
    {
        case 1:
            break;
        case 2:
            service = argv[1];
            break;
        default:
            errexit("too many arguments...\n");
    }

    msock = passiveTCP(service, QLEN);

    // reaper
    (void) signal(SIGCHLD, reaper);


    // fork() creates a new process by duplicating the calling process.
    // The new process, referred to as the child, is an exact duplicate of 
    // the calling process, referred to as the parent...
    // On success, the PID of the child process is returned in the parent, 
    // and 0 is returned in the child. On failure, -1 is returned in the parent,
    switch (fork())
    {
        case 0:    /* child */
            fork();
        default:   /* parent */
            break;
         case -1:
             errexit("fork: %s\n", strerror(errno));
    } // end switch

    while (1) // handle one client request per iteration.
    {
        alen = sizeof(fsin);
        // accept a client, get slave socket connected to that client.
        ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
        if (ssock < 0)
        {
            if (errno == EINTR)
                continue;
            errexit("accept: %s\n", strerror(errno));
        }
	else
	{
	    TCPbrowser(ssock);
	    close(ssock);
	    printf("im dead\n");
	}
    } // end while loop
} // end main
Exemple #3
0
/*------------------------------------------------------------------------
 * main - Iterative TCP server for DAYTIME service
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	struct	sockaddr_in fsin;	/* the from address of a client	*/
	char	*service = "daytime";	/* service name or port number	*/
	int	msock, ssock;		/* master & slave sockets	*/
	unsigned int	alen;		/* from-address length		*/

	switch (argc) {
	case	1:
		break;
	case	2:
		service = argv[1];
		break;
	default:
		errexit("usage: TCPdaytimed [port]\n");
	}

	msock = passiveTCP(service, QLEN);
	int fid;
	while (1) {
		alen = sizeof(fsin);
		ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
		if (ssock < 0)
			errexit("accept failed: %s\n", strerror(errno));
		else {
		if (fid = fork() == 0 ){

			TCPdaytimed(ssock);
			(void) close(ssock);
			}
		}
	}
}
Exemple #4
0
int
main(int argc, char *argv[])
{
        struct  sockaddr_in fsin;       /* the from address of a client */
        char    *service = get_port();   /* service name or port number  */
        int     msock, ssock;           /* master & slave sockets       */
        int     alen;                   /* from-address length          */

        switch (argc) {
        case    1:
                break;
        case    2:
                service = argv[1];
                break;
        default:
                errexit("<klaxon>\n");
        }

        msock = passiveTCP(service, QLEN);

        while (1) {
                alen = sizeof(fsin);
                ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
                if (ssock < 0)
                        errexit("accept failed: %s\n", strerror(errno));
                (void) Ttimed(ssock);
                (void) close(ssock);
        }
}
int main(int argc, char *arg[]) 
{
 char buffer[256]; 
 struct sockaddr_in6 fsin;
  char *service = "daytime";
  int msock, ssock;
 int alen,pid;
msock = passiveTCP(service, QLEN);
while (1)
 {  alen = sizeof(fsin); 
   ssock = accept(msock, (struct sockaddr *)&fsin, &alen); 
  if (ssock < 0)  
 {  printf("Error in accepting the socket connection\n");
    exit(0);
}  
 pid=fork();
 if(pid==0)
{  printf("This is a new client request\n");
   close(msock);
   TCPdaytimed(ssock); 
   exit(0);
}
}
close(ssock);
}
int main()  
{
	int msock, ssock, pid, clilen, cmd;
	struct sockaddr_in client_addr;   
	char *service = "ftp";
	pthread_t th;
	pthread_attr_t attr;
	pthread_attr_init(&attr);
	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);

	msock = passiveTCP(service, QLEN);

	clilen = sizeof(client_addr);

	while(1) 
	{ 
		/* ACCEPT A CONNECTION AND THEN CREATE A CHILD TO DO THE WORK */
		/* LOOP BACK AND WAIT FOR ANOTHER CONNECTION                  */
		printf("server: starting accept\n");
		ssock = accept(msock ,(struct sockaddr *) &client_addr, &clilen);
		if (ssock < 0)
		{
			printf("server: accept error: %d\n", errno); 
			exit(1); 
		}
		if (pthread_create(&th, &attr, doftp, (void *)(long)ssock))
		{	
			printf("server: pthread_create error: %s\n", strerror(errno));
			exit(1);
		}
	}
}   
Exemple #7
0
/*------------------------------------------------------------------------
 * main - Iterative server for DAYTIME service
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	char	*service = "daytime";	/* service name or port number	*/
	char	buf[LINELEN+1];		/* buffer for one line of text	*/
	struct sockaddr_in fsin;	/* the request from address	*/
	int	alen;			/* from-address length		*/
	int	tsock; 			/* TCP master socket		*/
	int	usock;			/* UDP socket			*/
	int	nfds;
	fd_set	rfds;			/* readable file descriptors	*/

	switch (argc) {
	case	1:
		break;
	case	2:
		service = argv[1];
		break;
	default:
		errexit("usage: daytimed [port]\n");
	}

	tsock = passiveTCP(service, QLEN);
	usock = passiveUDP(service);
	nfds = MAX(tsock, usock) + 1;	/* bit number of max fd	*/

	FD_ZERO(&rfds);

	while (1) {
		FD_SET(tsock, &rfds);
		FD_SET(usock, &rfds);

		if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0,
				(struct timeval *)0) < 0)
			errexit("select error: %s\n", strerror(errno));
		if (FD_ISSET(tsock, &rfds)) {
			int	ssock;		/* TCP slave socket	*/

			alen = sizeof(fsin);
			ssock = accept(tsock, (struct sockaddr *)&fsin,
				&alen);
			if (ssock < 0)
				errexit("accept failed: %s\n",
						strerror(errno));
			daytime(buf);
			(void) write(ssock, buf, strlen(buf));
			(void) close(ssock);
		}
		if (FD_ISSET(usock, &rfds)) {
			alen = sizeof(fsin);
			if (recvfrom(usock, buf, sizeof(buf), 0,
				(struct sockaddr *)&fsin, &alen) < 0)
				errexit("recvfrom: %s\n",
					strerror(errno));
			daytime(buf);
			(void) sendto(usock, buf, strlen(buf), 0,
				(struct sockaddr *)&fsin, sizeof(fsin));
		}
	}
}
Exemple #8
0
int main()  
{
	int msock, sel;
	char *service = "ftp";
	enum selection option;

	printf("Please enter number to select corresponding option:\n");
	printf("0: select\n1:fork\n2:thread\n");
	scanf("%d", &sel);
	option = sel;

	msock = passiveTCP(service, QLEN);

	switch(option)
	{
		case SELECT: 
			printf("SELECT option was selected\n");
			do_select(msock);
			break;
		case FORK:
			printf("FORK option was selected\n");
			do_fork(msock);
			break;
		case THREAD:
			printf("THREAD option was selected\n");
			do_thread(msock);
			break;
		default:	
			printf("Invalid option\n");
			exit(1);
	}

}   
Exemple #9
0
int main(int argc, char  *argv[]) 
{
	int csd; /* client & server socket descriptors */
	char    *service="12345";       /* service name or port number --default value  */
        struct  sockaddr_in cli_addr;    /* the address of a client   */
        unsigned int    size;      /* length of client's address   */
	//struct sockaddr_in serv_addr;
	struct sigaction sa;
	pthread_t *threads;


	switch (argc) //switch case to properly check the command line arguments
        {
        	case 1:
			break;	//to be removed after
		case 2:
                	service = argv[1]; //assigning the service value given by user.
                	break;
        	default:
			set_output_error_color();
                	printf("usage: td <port>\n");
			set_output_default_color();
			exit(1);
        }
                                                                                              
        printf("%s", "Server is beginning...\n"); //call this routine to create socket.
	
	ssd = passiveTCP(service, QLEN); //create slave socket descriptor
	
	/*
	sa.sa_handler = sig_handler;
	sigemptyset(&sa.sa_mask);
	sa.sa_flags = SA_RESTART;
	if(sigaction(SIGCHLD, &sa, NULL) == -1) {
		perror("sigaction");
		exit(1);
	}*/ //have to dig through

	while(1) 
	{
		size = sizeof(cli_addr);
		printf("Waiting for the CLIENT connections...\n");
		if((csd=accept(ssd,(struct sockaddr*)&cli_addr,&size))==-1)
		{
			perror("accept");
			continue;
		}
		printf("server: Connection recvd from %s\n",inet_ntoa(cli_addr.sin_addr));
	        threads=(pthread_t *)malloc(sizeof(pthread_t));
		
		if(pthread_create(threads,NULL,telnetSession,(void*)&csd)!=0)
			perror("pthread_create"); //start the Telnet session	
		//telnetSession(csd,ssd); //start the Telnet session	
		//if(close(csd) <0) //close the Client socket descriptor
		//	perror("close:"); 

	}// end of while(1)
	return 0;
}//end of MAIN()
Exemple #10
0
/*------------------------------------------------------------------------
 * main - Concurrent TCP server for ECHO service
 *------------------------------------------------------------------------
 */
int main(int argc, char *argv[])
{
	pthread_t	th;
	pthread_attr_t	ta;
	/*char	*service = "echo";	/* service name or port number	*/
	char	*service = "10000";
	struct	sockaddr_in fsin,cli;	/* the address of a client	*/
	
	unsigned int	alen,clen;		/* length of client's address	*/
	int	msock;					/* master server socket		*/
	int	ssock;					/* slave server socket		*/
	char				buff[BUFSIZE];


	/*switch (argc) {
	case	1:
		break;
	case	2:
		service = argv[1];
		break;
	default:
		errexit("usage: TCPechod [port]\n");
	}*/

	msock = passiveTCP(service, QLEN);

	(void) pthread_attr_init(&ta);
	(void) pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
	(void) pthread_mutex_init(&stats.st_mutex, 0);

	if (pthread_create(&th, &ta, (void * (*)(void *))prstats, 0) < 0)
		errexit("pthread_create(prstats): %s\n", strerror(errno));

	while (1) {
		alen = sizeof(fsin);
		clen = sizeof(cli);
		//ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
		ssock = accept(msock, (struct sockaddr *)&cli, &clen);
		//fsin.sin_addr.s_addr=htonl(fsin.sin_addr.s_addr);
		//inet_ntoa(adr_inet.sin_addr)
		//(struct sockaddr *)&fsin, &alen)
		//printf("connection from %d, port %d\n",
		//	   Inet_ntop(AF_INET, &cli.sin_addr, buff, sizeof(buff)), ntohs(cli.sin_port));
		//getpeername(ssock,(struct sockaddr *)&fsin, &alen);
		
		//(void) printf("%d\n", getpeername(ssock,(struct sockaddr *)&nm, &nlen));
		//(void) printf("%s\n", inet_ntoa(addr.sin_addr));
		//(void) printf("%lu\n", fsin.sin_addr.s_addr);
		//fsin.sa_data sin_addr
		//inet_ntoa((struct sockaddr *)&fsin.sa_data)
		if (ssock < 0) {
			if (errno == EINTR)
				continue;
			errexit("accept: %s\n", strerror(errno));
		}
		if (pthread_create(&th, &ta, (void * (*)(void *))TCPechod, (void *)ssock) < 0)
			errexit("pthread_create: %s\n", strerror(errno));
	}
}
Exemple #11
0
/*------------------------------------------------------------------------
 * main - Concurrent TCP server for ECHO service
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	char	*service = "echo";	/* service name or port number	*/
	struct sockaddr_in fsin;	/* the from address of a client	*/
	int	msock;			/* master server socket		*/
	fd_set	rfds;			/* read file descriptor set	*/
	fd_set	afds;			/* active file descriptor set	*/
	unsigned int	alen;		/* from-address length		*/
	int	fd, nfds;
	
	switch (argc) {
	case	1:
		break;
	case	2:
		service = argv[1];
		break;
	default:
		errexit("usage: TCPmechod [port]\n");
	}

	msock = passiveTCP(service, QLEN);

	nfds = getdtablesize();
	FD_ZERO(&afds);
	FD_SET(msock, &afds);

	while (1) {
		memcpy(&rfds, &afds, sizeof(rfds));

		if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0,
				(struct timeval *)0) < 0)
			errexit("select: %s\n", strerror(errno));
		if (FD_ISSET(msock, &rfds)) {
			int	ssock;

			alen = sizeof(fsin);
			ssock = accept(msock, (struct sockaddr *)&fsin,
				&alen);
			if (ssock < 0)
				errexit("accept: %s\n",
					strerror(errno));
			FD_SET(ssock, &afds);
		}
		for (fd=0; fd<nfds; ++fd)
			if (fd != msock && FD_ISSET(fd, &rfds))
				if (echo(fd) == 0) {
					(void) close(fd);
					FD_CLR(fd, &afds);
				}
	}
}
Exemple #12
0
/*------------------------------------------------------------------------
 * main - Super-server main program
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
  struct service  *psv,    /* service table pointer  */
    *fd2sv[NOFILE];    /* map fd to service pointer  */
  int  fd, nfds;
  fd_set  afds, rfds;    /* readable file descriptors  */

  switch (argc) {
  case 1:
    break;
  case 2:
    portbase = (u_short) atoi(argv[1]);
    break;
  default:
    errexit("usage: superd [portbase]\n");
  }

  nfds = 0;
  FD_ZERO(&afds);
  for (psv = &svent[0]; psv->sv_name; ++psv) {
    if (psv->sv_useTCP)
      psv->sv_sock = passiveTCP(psv->sv_name, QLEN);
    else
      psv->sv_sock = passiveUDP(psv->sv_name);
    fd2sv[psv->sv_sock] = psv;
    nfds = MAX(psv->sv_sock+1, nfds);
    FD_SET(psv->sv_sock, &afds);
  }
  (void) signal(SIGCHLD, reaper);

  while (1) {
    memcpy(&rfds, &afds, sizeof(rfds));
    if (select(nfds, &rfds, (fd_set *)0, (fd_set *)0,
        (struct timeval *)0) < 0) {
      if (errno == EINTR)
        continue;
      errexit("select error: %s\n", strerror(errno));
    }
    for (fd=0; fd<nfds; ++fd)
      if (FD_ISSET(fd, &rfds)) {
        psv = fd2sv[fd];
        if (psv->sv_useTCP)
          doTCP(psv);
        else
          psv->sv_func(psv->sv_sock);
      }
  }
}
/*------------------------------------------------------------------------
 * main - Concurrent TCP server for ECHO service
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	pthread_t	th;
	pthread_attr_t	ta;
	char	*service = "echo";	/* service name or port number	*/
	struct	sockaddr_in fsin;	/* the address of a client	*/
	unsigned int	alen;		/* length of client's address	*/
	int	msock;			/* master server socket		*/
	int	ssock;			/* slave server socket		*/

	switch (argc) {
	case	1:
		break;
	case	2:
		service = argv[1];
		break;
	default:
		errexit("usage: TCPechod [port]\n");
	}

	msock = passiveTCP(service, QLEN);

	(void) pthread_attr_init(&ta);
	(void) pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
	(void) pthread_mutex_init(&stats.st_mutex, 0);

	if (pthread_create(&th, &ta, (void * (*)(void *))prstats, 0) < 0)
		errexit("pthread_create(prstats): %s\n", strerror(errno));

	while (1) {
		alen = sizeof(fsin);
		ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
		if (ssock < 0) {
			if (errno == EINTR)
				continue;
			errexit("accept: %s\n", strerror(errno));
		}
		if (pthread_create(&th, &ta, (void * (*)(void *))TCPechod,
		    (void *)(long)ssock) < 0)
			errexit("pthread_create: %s\n", strerror(errno));
	}
}
Exemple #14
0
int main(int argc, char *argv[])
{
	pthread_t th;
	pthread_attr_t ta;

        struct  sockaddr_in fsin;       /* the from address of a client */
        char    *service = get_port();   /* service name or port number  */
        int     msock, ssock;           /* master & slave sockets       */
        int     alen;                   /* from-address length          */
	int childpid;

	signal(SIGPIPE,SIG_IGN);
	signal(SIGCHLD,reaper);
        switch (argc) {
        case    1:
                break;
        case    2:
                service = argv[1];
                break;
        default:
                errexit("<klaxon>\n");
        }

        msock = passiveTCP(service, QLEN);
	
	printf("Server listening on:  %s\n",get_port());
	alen = sizeof(fsin);

	(void) pthread_attr_init(&ta);
	(void) pthread_attr_setdetachstate(&ta, PTHREAD_CREATE_DETACHED);
	while (  
		((ssock = accept(msock, (struct sockaddr *)&fsin, &alen)) >= 0) &&
		(pthread_create(&th,&ta,(void * (*) (void *))serv,(void *) ssock) == 0 )
	      );
	printf("alen: %i\tssock: %i\tchildpid: %i\n",alen,ssock,childpid);
	/*
	if(childpid == 0) {
		close(msock);
		while(serv(ssock));
		exit(0);
	} else errexit("<beep>");
	*/
}
/*------------------------------------------------------------------------
 * main - Iterative TCP server for DAYTIME service
 *------------------------------------------------------------------------
 */
int
main(int argc, char *argv[])
{
	struct	sockaddr_in fsin;	/* the from address of a client	*/
	char	*service = "daytime";	/* service name or port number	*/
	int	msock, ssock;		/* master & slave sockets	*/
	unsigned int	alen;		/* from-address length		*/
	pid_t pid;
	int status;

	switch (argc) {
	case	1:
		break;
	case	2:
		service = argv[1];
		break;
	default:
		errexit("usage: TCPdaytimed [port]\n");
	}

	msock = passiveTCP(service, QLEN);

	while (1) {
		alen = sizeof(fsin);
		ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
		if (ssock < 0)
			errexit("accept failed: %s\n", strerror(errno));
		
		if((pid = fork()) == 0)		/*create child process and run if successful*/
		{
			close(msock);		/*In slave prcess close master socket*/ 
			printf("\nI am in child process, pid is:%d and parent id is:%d\n", getpid(), getppid());
			TCPdaytimed(ssock);	/*call tcpdaytimed function*/
			(void) close(ssock);	/*after function call close slave socket*/
			exit(0);
		}
	}
}
Exemple #16
0
int main(int argc, char *argv[])
{
	int sockfd, new_sockfd;
	const char *port = "9001";

	sockfd = passiveTCP(port,QLEN);
	if (sockfd < 0)
		error("ERROR opening socket");
		
	while(1)
	{
		if(new_sockfd = accept(sockfd, 0, 0))
		{
			pthread_t t;
			pthread_create(&t, 0, do_proxy, (void*)new_sockfd);
		}
	}


	close(new_sockfd);
	close(sockfd);
	
	return 0;
}
int main(int argc, char*argv[]) {
char *service = "daytime";
	char buf[LINELEN + 1];
	struct sockaddr_in fsin;
	unsigned int alen;
	int tsock;
	int usock;
	int nfds;
	fd_set rfds;


	tsock = passiveTCP("tcp", QLEN);
	usock = passiveUDP("udp");
	nfds = MAX(tsock, usock) + 1;

	FD_ZERO(&rfds);

	while (1) {
		FD_SET(tsock, &rfds);
		(usock, &rfds);

		if (select(nfds, &rfds, (fd_set *) 0, (fd_set *) 0,
				(struct timeval *) 0) < 0)
			errexit("select error : %s\n", strerror(errno));

		if (FD_ISSET(tsock, &rfds)) {
			int ssock;
			pthread_t thread_id;
			alen = sizeof(fsin);
			ssock = accept(tsock, (struct sockaddr *) &fsin, &alen);
			if (ssock < 0)
				errexit("accept failed: %s\n", strerror(errno));

			if (pthread_create(&thread_id, NULL, connection_handler,
					(void*) &ssock) < 0) {
				perror("could not create thread");
				return 1;
			}

			daytime(buf);
			(void) write(ssock, buf, strlen(buf));
			(void) close(ssock);
		}

		if (FD_ISSET(usock, &rfds)) {
			alen = sizeof(fsin);
			pthread_t thread_id;
			if (recvfrom(usock, buf, sizeof(buf), 0, (struct sockaddr *) &fsin,
				&alen) < 0)
			errexit("recvfrom: %s\n", strerror(errno));

			if (pthread_create(&thread_id, NULL, connection_handlerudp,
					(void*) &usock) < 0) {
				perror("could not create thread");
				return 1;
			}
			daytime(buf);
			(void) sendto(usock, buf, strlen(buf), 0, (struct sockaddr*) &fsin,
					sizeof(fsin));
		}
}

void *connection_handlerudp(void *socket_desc) {

	char buf[LINELEN + 1];
	unsigned int alen;
	struct sockaddr_in fsin;
	int readsize;
	int sock = *(int*) socket_desc;
	alen = sizeof(fsin);
	while ((readsize = recvfrom(sock, buf, sizeof(buf), 0,
			(struct sockaddr *) &fsin, &alen)) > 0) {
		sendto(sock, buf, sizeof(buf), 0, (struct sockaddr *) &fsin,
				sizeof(fsin));
	}

	if (readsize == 0) {
		puts("Client disconnected");
		fflush(stdout);
	} else if (readsize == -1) {
		perror("recv failed");
	}
	errexit("recvfrom: %s\n", strerror(errno));


}
Exemple #18
0
// multiple-protocol super server
int
main(int argc, char **argv)
{
	Service *psv, *fd2sv[NOFILE];
	int fd, nfds;
	fd_set afds, rfds;

	// set port base
	portbase = 0;

	// check the arguments
	switch (argc)
	{
	case 1:
		break;
	case 2:
		portbase = atoi(argv[1]);
		break;
	default:
		ERROR("usage: superd [portbase]", EINVAL);
		return(1);
	}

	// signal handlers for exiting
	setCleanUp();

	// check of any port base offset
	if (portbase == 0)
		checkPortBase();

	// initialize array of services
	nfds = 0;
	FD_ZERO(&afds);
	for (psv = services; psv->service != NULL; psv++)
	{
		// allocate a socket
		switch (psv->protocol)
		{
		case UseUDP:
			psv->socket = passiveUDP(psv->service);
			if (psv->socket < 0)
			{
				ERRORD("passiveUDP failed", 
					psv->socket, errno);
				return(2);
			}
			break;

		case UseTCP:
			psv->socket = passiveTCP(psv->service, QueueLength);
			if (psv->socket < 0)
			{
				ERRORD("passiveTCP failed", 
					psv->socket, errno);
				return(2);
			}
			break;

		default:
			ERROR("invalid protocol in service table", EINVAL);
			return(2);
		}

		// map descriptor to service
		fd2sv[psv->socket] = psv;
		nfds = mymax(psv->socket+1, nfds);
		FD_SET(psv->socket, &afds);
	}

	// wait for a message and process it.
	while (1)
	{
		// copy active descriptors
		memcpy(&rfds, &afds, sizeof(rfds));

		// wait for a calling
		if (select(nfds, &rfds, 0, 0, 0) < 0)
		{
			if (errno == EINTR)
				continue;
			ERROR("select error", errno);
			return(2);
		}

		// process active descriptors
		for (fd = 0; fd < nfds; fd++)
		{
			// check if active
			if ( ! FD_ISSET(fd, &rfds))
				continue;

			// active, process according to protocol
			psv = fd2sv[fd];
			switch (psv->protocol)
			{
			case UseTCP:
				doTCP(psv);
				break;

			case UseUDP:
				psv->server(psv->socket);
				break;

			default:
				ERRORD("invalid protocol", 
					psv->protocol, EINVAL);
				return(2);
			}
		}
	}
}
int main()
{
	struct sockaddr_in cli_addr;
	int msock, ssock, rsock;
	/* ssock is sock between browser and socks server, rosk is sock between server and socks server*/
	int alen;
	int childpid;

	gSocksConfig = NULL; /*global var recording for config content*/
	msock = passiveTCP(SERVER_PORT, 5);
	// create socket waiting for client's link
	fprintf(stdout, "Server is listening on 140.113.215.186 %d\n", SERVER_PORT);

	//************************************
	// read firewall rule from socks.conf
	//************************************
	if(readSocksConfig() == FAILURE)
	{
		fprintf(stdout, "File: socks.conf parse error\n");
		return 0;
	}
	else
	{
		//************************************
		// use linking list to print out socks.conf content
		//************************************
		socksConfig *printTest;
		printTest = gSocksConfig; /* point to global socksConfig */
		while(printTest)
		{
			fprintf(stdout, "rule: %s, linking: %d, s_IP: %s, s_Port: %d, d_IP: %s, d_Port: %d\n", \
					(printTest->ruleState == PERMIT) ? "PERMIT" : "DENY", printTest->linkingType, \
					printTest->srcIP, printTest->srcPort, printTest->dstIP, printTest->dstPort);
			printTest = printTest->next;
		}
	}

	while(1)
	{
		alen = sizeof(cli_addr);
		ssock = accept(msock, (struct sockaddr *)&cli_addr, &alen);
		if(ssock < 0) 
		{
			fprintf(stderr, "accept error: %s\n", strerror(errno));
			continue;
		}

		if((childpid = fork()) < 0)
		{
			fprintf(stderr , "fork error\n");
			close(ssock);
		}
		else if(childpid == 0)
		// create new process to handle new socks connection
		{
			close(msock);

			int readLen, writeLen = 0, writeOutLen = 0, rsock = -1;/* writeOutLen is for non-blocking write*/
			socks4Packet *pMsgPacket = NULL, *pRepPacket = NULL; 
			/* pMsgPacket is used to receive data packet from client, pRepPacket is for replying*/
			struct sockaddr_in passSin;
			int passLen = sizeof(passSin);

			pMsgPacket = allocScoks4Packet();

			if((readLen = recvMsg(ssock, pMsgPacket->dataBuf, DATABUFLEN)) < 0)
			// receive request and save in buf
			{
				fprintf(stderr, "Recv msg error: %s\n", strerror(errno));
				socksBreak(pMsgPacket, pRepPacket, ssock, rsock);
				exit(0);
			}

			if(parseMsgPacket(pMsgPacket) != SUCCESS)
			// parse receive packet
			{
				fprintf(stderr, "Parse msg error\n");
				socksBreak(pMsgPacket, pRepPacket, ssock, rsock);
				exit(0);
			}

			//************************************
			// after parsing socks packet, save related info in pMsgPacket, then check with socks.conf rule
			//
			// rsock == -1 or psock == 1, my program will reply invalid packet(CD == 91) to client
			//************************************
			if(checkPacketWithConfig(pMsgPacket, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port)) == false)
			{
				pMsgPacket->rsock = -1;
				pMsgPacket->psock = -1;
			}
			else
			{
				//************************************
				// if CONNECT mode, help client to connect remote server
				//
				// else if BIND mode, listen on a local mode, and wait for remote server to connect
				//************************************
				if(pMsgPacket->CD == CONNECT)
					pMsgPacket->rsock = dstConnect(pMsgPacket);
				else if(pMsgPacket->CD == BIND)
				{
					if((pMsgPacket->psock = passiveTCP(0, 5)) > -1)
					{
						bzero((char *)&passSin, sizeof(passSin));
						getsockname(pMsgPacket->psock, (struct sockaddr *)&passSin, &passLen);
						// use getsockname to get the bind port (assigned by system)
						pMsgPacket->dstPort = ntohs(passSin.sin_port);
					}
				}
			}

			pRepPacket = allocScoks4Packet();

			//************************************
			// create reply packet via parsing result
			//
			// and print out packet content and parsing result
			//************************************
			if(creatRepPacket(pMsgPacket, pRepPacket) != SUCCESS)
			{
				fprintf(stderr, "Packet create error\n");
				socksBreak(pMsgPacket, pRepPacket, ssock, \
						pMsgPacket->CD == CONNECT ? pMsgPacket->rsock : pMsgPacket->psock);
				exit(0);
			}
			else
			{
				fprintf(stdout, "<S_IP>: %s, <S_PORT>: %d, <VN>: %u, <CD>: %u, <D_IP>: %s, <D_PORT>: %d, <CMD>: %s, <REPLY>: %s\n",\
						inet_ntoa(cli_addr.sin_addr),ntohs(cli_addr.sin_port), pMsgPacket->VN, \
						(pMsgPacket->CD == CONNECT) ? 1 : 2, \
						(pMsgPacket->domainName == NULL)? pMsgPacket->dstIP : pMsgPacket->domainName, \
						pMsgPacket->dstPort, (pMsgPacket->CD == CONNECT) ? "CONNECT" : "BIND", \
						(pRepPacket->CD == 90) ? "ACCEPT" : "REJECT");
			}

			//************************************
			// send reply packet to client
			//************************************
			while(writeOutLen < SOCKSREPLAYLEN)
			{
				writeLen = sendMsg(ssock, pRepPacket->dataBuf + writeOutLen, SOCKSREPLAYLEN - writeOutLen);	
				writeOutLen += writeLen;
			}

			// invalid request packet
			if((pMsgPacket->CD == CONNECT && pMsgPacket->rsock == -1) ||\
					(pMsgPacket->CD == BIND && pMsgPacket->psock == -1))
			{
				if(pMsgPacket->CD == CONNECT)
					fprintf(stderr, "CONNECT: Invalid remote host\n");
				else if(pMsgPacket->CD == BIND)
					fprintf(stderr, "BIND: Invalid socks server port/socket\n");

				socksBreak(pMsgPacket, pRepPacket, ssock, \
						pMsgPacket->CD == CONNECT ? pMsgPacket->rsock : pMsgPacket->psock);
				exit(0);
			}

			//************************************
			// if BIND mode, wait for server to connect, then reply success msg to client
			//************************************
			if(pMsgPacket->CD == BIND)
			{
				unsigned char secReplyPacket[DATABUFLEN];

				memset(secReplyPacket, 0, DATABUFLEN);
				bzero((char *)&passSin, sizeof(passSin));
				writeOutLen = 0;

				pMsgPacket->rsock = accept(pMsgPacket->psock, (struct sockaddr *)&passSin, &passLen);

				//************************************
				// msg format: 0 (0x5A or 0x5B) ignore ignore
				//************************************
				secReplyPacket[0] = 0;
				secReplyPacket[1] = (pMsgPacket->rsock < 0) ? 91 : 90;

				while(writeOutLen < SOCKSREPLAYLEN)
				{
					writeLen = sendMsg(ssock, secReplyPacket + writeOutLen, \
							SOCKSREPLAYLEN - writeOutLen);	
					writeOutLen += writeLen;
				}

				// fail, exit anyway
				if(pMsgPacket->rsock < 0) 
				{
					fprintf(stderr, "BIND: accept error: %s\n", strerror(errno));
					close(pMsgPacket->rsock);
					socksBreak(pMsgPacket, pRepPacket, ssock, \
							pMsgPacket->CD == CONNECT ? pMsgPacket->rsock : pMsgPacket->psock);
					exit(0);
				}
			}

			//************************************
			// help client and server do packet exchange
			//************************************
			relayData(ssock, pMsgPacket->rsock);

			socksBreak(pMsgPacket, pRepPacket, ssock, \
					pMsgPacket->CD == CONNECT ? pMsgPacket->rsock : pMsgPacket->psock);
			freeSocksConfig();
			fprintf(stdout, "One client is leaving and its IP and port are %s and %d\n",\
					inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
			exit(0);
		}
		else
		// close sock with client
			close(ssock);
	}
	close(msock);
	freeSocksConfig();
	return 0;
}