Example #1
0
/**
 * server_init
 *
 * Creates a socket and puts the socket into a listening mode
 *
 * @param s server structure variable.
 */
void server_init(server *s) {
	const int on = 1;
	struct sockaddr_in servaddr;

	/* create TCP socket to listen for client connections */
	fprintf(stderr, "Creating TCP socket\n");
	s->listen_sd = socket(AF_INET, SOCK_STREAM, 0);
	if (s->listen_sd < 0)
		SystemFatal("Socket Creation Failed\n");

	/* set the socket to allow re-bind to same port without wait issues */
	setsockopt(s->listen_sd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (int));

	/* make the server Socket non-blocking */
	if (fcntl(s->listen_sd, F_SETFL, O_NONBLOCK | fcntl(s->listen_sd, F_GETFL, 0)) == -1)
		SystemFatal("fcntl(): Server Non-Block Failed\n");

	bzero(&servaddr, sizeof (servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(s->port);

	if (bind(s->listen_sd, (struct sockaddr *) &servaddr, sizeof (servaddr)) < 0)
		SystemFatal("Failed to bind socket\n");

	/* setup the socket for listening to incoming connection  */
	if (listen(s->listen_sd, LISTENQ) < 0)
		SystemFatal("Unable to listen on socket \n");

	/* right now the listening socket is the max */
	s->maxfd = s->listen_sd;

}
Example #2
0
/**
 * main
 *
 * Parses the user commandline input and creates and waits for the
 * server thread.
 *
 * @param argc number of command line arguments
 * @param argv the command line arguments
 * @return EXIT_SUCCES after successful completion.
 */
int main(int argc, char** argv) {

	int ret;
	struct sigaction act;
	server *s;

	act.sa_handler = signal_Handler;
	act.sa_flags = 0;

	if ((sigaction(SIGINT, &act, NULL) == -1)) {
		SystemFatal("Failed to set SIGINT handler\n");
	}
	if ((sigaction(SIGPIPE, &act, NULL) == -1)) {
		SystemFatal("Failed to set SIGPIPE handler\n");
	}
	if ((sigaction(SIGSEGV, &act, NULL) == -1)) {
		SystemFatal("Failed to set SIGPIPE handler\n");
	}
	/* creates a new server variable and initialize the structure. */
	s = server_new();
	serv = s;

	switch (argc) {
	case 1:
		s->port = SERVER_TCP_PORT; // Use the default port
		break;
	case 2:
		s->port = atoi(argv[1]); // Get user specified port
		break;
	default:
		fprintf(stderr, "Usage: %s [port]\n", argv[0]);
		exit(1);
	}

	ret = pthread_create(&master_manager, NULL, client_manager, s);
	if (ret != 0)
		SystemFatal("Unable to create client management thread\n");

	pthread_join(master_manager, NULL);

	free(s);

	return (EXIT_SUCCESS);
}
Example #3
0
/**
 * client_manager
 *
 * Thread function to manage client connections.
 *
 * @param data Thread data for the function
 */
void* client_manager(void *data) {
	int nready;
	client *c = NULL;
	node *n = NULL;
	server *s = (server *)data;

	/* set up as a tcp server */
	server_init(s);

	while (running) {
		pthread_mutex_lock(&s->dataLock);

		FD_ZERO(&s->allset);
		FD_SET(s->listen_sd, &s->allset);

		/* loop through all possible socket connections and add
		 * them to fd_set */
		for (n = s->client_list->link; n != NULL; n = n->next) {
			c = (client *)n->data;
			FD_SET(c->fd, &s->allset);
			if (c->fd > s->maxfd)
				s->maxfd = c->fd;
		}

		/* Monitor sockets for any activity of new connections or data transfer */
		nready = select(s->maxfd + 1, &s->allset, NULL, NULL, NULL);

		pthread_mutex_unlock(&s->dataLock);

		if (nready < 0) {
			/* Something interrupted the call, cause EINTR, continue */
			if (errno == EINTR)
				continue;
			else
				SystemFatal("Select() Error\n");
		}
		else if (nready == 0) {
			/* nothing to read, continue */
			continue;
		}
		else {
			/* There is an activity on one or more sockets. */
			read_from_socket(s);
		}
	}

	fprintf(stdout, "Exiting the client manager\n");
	close(s->listen_sd);
	free(s);
	pthread_exit(NULL);
}
Example #4
0
/**
 * process_client_data
 *
 * Processes the current client command that triggered an event
 *
 * @param c the client data containing the file descriptor to write to.
 */
void process_client_data(client *c, server *s) {
	ssize_t r, w;
	int bytes_to_read = BUFLEN;
	char error[100], recvBuff[BUFLEN], sendBuff[BUFLEN];
	//char *recv;
	//recv = malloc(BUFLEN * sizeof (char));
	while ((r = read(c->fd, recvBuff, bytes_to_read)) > 0) {
		//recv += r;
		recvBuff[r] = 0;
		s->n_max_bytes_received += r;
		bytes_to_read -= r;
	}
	//printf("%s\n", recvBuff);
	strcpy(sendBuff, recvBuff);
	if ((w = write(c->fd, sendBuff, BUFLEN)) != BUFLEN) {
		strcpy(error, "Client Write Error - ");
		sscanf(error, "%d != %d\n", (int *)strlen(recvBuff), (int *)w);
		SystemFatal(error);
	}
	c->quit = true;
	return;
	//n = readline (c->fd, recv, BUFLEN);
}
Example #5
0
/**
 * server_new
 *
 * Creates a server structure and initializes the variables
 *
 * @return s Returns the server structure
 */
server* server_new(void) {
	//int i;
	server *s = malloc(sizeof (server));
	if (s == NULL)
		SystemFatal("Malloc() Failed \n");

	s->pid = getpid();
	s->n_clients = 0;
	s->n_max_connected = 0;
	s->n_max_bytes_received = 0;

	s->client_list = llist_new();

	/*for (i = 0; i <= FD_SETSIZE; i++) {
		s->clients[i] = -1;
		}*/

	if (pthread_mutex_init(&s->dataLock, NULL) != 0) {
		free(s);
		return NULL;
	}

	return s;
}
Example #6
0
/**
 * process_client_req
 *
 * process the client request and responses with data, or starts the closing
 * procedure
 *
 * @param c client information
 * @param s server information
 */
void process_client_req(client *c, server *s) {
	ssize_t r, w;
	char *recv;
	//int bytes_to_read = BUFLEN;
	char error[100];

	recv = malloc(BUFLEN * sizeof (char));

	while ((r = read(c->fd, recv, BUFLEN)) > 0) {
		s->n_max_bytes_received += r;
	}

	if (strcmp(recv, "request\n") == 0) {
		if ((w = write(c->fd, client_msg, BUFLEN)) != BUFLEN) {
			strcpy(error, "write(): Client Write Error - ");
			sscanf(error, "%d != %d\n", (int *)strlen(recv), (int *)w);
			SystemFatal(error);
		}
	}
	else if (strcmp(recv, "quit\n") == 0) {
		c->quit = true;
		return;
	}
}
Example #7
0
int main (int argc, char **argv)
{
	int	n, bytes_to_read, ret, yes = 1;
	int	sd, new_sd, client_len;
	char	*bp, buf[BUFLEN];
	struct sockaddr_in6 client; 
	struct addrinfo query,*response,*ap;
  	struct linger cflinger;
	char hostname[MAXSTR], service[MAXSTR];
	static const char *server_port = SERVER_TCP_PORT;
		
	// Initialize cflinger - this option will ensure that the connection "close" will block until all the data is delivered
	cflinger.l_onoff = 1; // non zero will block close 
	cflinger.l_linger = 60; // until timeout


	switch(argc)
	{
		case 1:
			server_port = SERVER_TCP_PORT;	// Use the default port
		break;
		case 2:
			server_port = argv[1];	// Get user specified port
		break;
		default:
			fprintf(stderr, "Usage: %s [port]\n", argv[0]);
			exit(1);
	}


	// Get the the address info from the NIC
	bzero (&query,sizeof(struct addrinfo));

	query.ai_flags = AI_PASSIVE;	// Passive Open
	query.ai_family = AF_UNSPEC;	// Either IPv4 or IPv6 
	query.ai_socktype = SOCK_STREAM;
	
	if ((ret = getaddrinfo (NULL, server_port, &query, &response)) != 0)
	{
		printf("%s",gai_strerror(ret));
		exit (1);
	}
	
	sd = -1;
	for (ap = response ; ap != NULL; ap=ap->ai_next)
  	{
   		if ((sd = socket (ap->ai_family,ap->ai_socktype,ap->ai_protocol)) == -1)
      			continue;
      		
   		if (setsockopt (sd, SOL_SOCKET, SO_REUSEADDR, (char *) &yes, sizeof (int)) == -1)
      			SystemFatal("setsockopt");
		   
   		if (setsockopt (sd, SOL_SOCKET, SO_LINGER, (char *) &cflinger, sizeof (struct linger)) == -1)
      			SystemFatal("setsockopt");
   
   		if (bind(sd,ap->ai_addr,ap->ai_addrlen) == 0)
      			break; // success 
      		   
   		close(sd);
   		sd = -1;
		SystemFatal("bind");
   	}

	freeaddrinfo(response);

	if (sd < 0)
		SystemFatal ("Cannot bind the open socket");
   	 
	
	// Listen for connections
	// queue up to 5 connect requests
	if (listen (sd, QUEUE) == -1)
   		SystemFatal("listen");

	while (TRUE)
	{
		bzero (hostname, MAXSTR);
  		bzero (service, MAXSTR);

		client_len= sizeof (client);
		if ((new_sd = accept (sd, (struct sockaddr *)&client, &client_len)) == -1)
      			SystemFatal("accept");		

		if (getnameinfo ((struct sockaddr *)&client, client_len, hostname, MAXSTR, service, MAXSTR, 0) != 0)
			SystemFatal("getnameinfo");     		

  		printf ("Remote Address: (%s) on Remote Port (%s)\n", hostname, service);
  
		bp = buf;
		bytes_to_read = BUFLEN;
		while ((n = recv (new_sd, bp, bytes_to_read, 0)) < BUFLEN)
		{
			bp += n;
			bytes_to_read -= n;
		}
		
		if (strncmp("server-halt", buf, 11) == 0)
		{
			printf ("sending:%s\n", buf);
			send (new_sd, buf, BUFLEN, 0);
			close (new_sd);
                	break;
		}
		else
		{
			printf ("sending:%s\n", buf);
			send (new_sd, buf, BUFLEN, 0);
			close (new_sd);
		}
	}
	
	close (sd);
	printf ("Server shutting down...\n");
	return (0);
}
// This is the main function which handles the epoll loop and 
// accepts connections
// Also handles the data processing back to the client.
int main (int argc, char* argv[]) 
{
    int i, arg, src_port, forwardSD, dest_port;
    int num_fds, fd_new, epoll_fd;
    int linenum=0;
    static struct epoll_event events[EPOLL_QUEUE_LEN], event;
    struct sockaddr_in addr, remote_addr;
    socklen_t addr_size = sizeof(struct sockaddr_in);
    struct sigaction act;
    struct  hostent *hp;
    struct  sockaddr_in server_fwd;
    char *host;
        char line[256], ip[256];
    FILE *fp;

    fp=fopen("port_forward_config", "r");
    //src_port = LISTEN_PORT;           // Use the default listen port


        while(fgets(line, 256, fp) != NULL)
        {
                linenum++;
                if(line[0] == '#') continue;

                sscanf(line, "%s %d %d", &ip, &src_port, &dest_port);
        {
                    fprintf(stderr, "Syntax error, line %d\n", linenum);
                continue;
        }
    }
    printf("Reading Config File...\n");
    printf("IP %s LPORT %d DPORT %d\n", ip, src_port, dest_port);
    host = ip;

    // set up the signal handler to close the server socket when CTRL-c is received
    act.sa_handler = close_fd;
    act.sa_flags = 0;
    if ((sigemptyset (&act.sa_mask) == -1 || sigaction (SIGINT, &act, NULL) == -1))
    {
            perror ("Failed to set SIGINT handler");
            exit (EXIT_FAILURE);
    }
//--------------------------------------------------------------------------------------------  
    // Create the listening socket
    fd_server = socket (AF_INET, SOCK_STREAM, 0);
    if (fd_server == -1) 
    {   
        SystemFatal("socket");
    }
    // set SO_REUSEADDR so port can be resused imemediately after exit, i.e., after CTRL-c
    arg = 1;
    if (setsockopt (fd_server, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1) 
    {   
        SystemFatal("setsockopt");
    }
    // Make the server listening socket non-blocking
    if (fcntl (fd_server, F_SETFL, O_NONBLOCK | fcntl (fd_server, F_GETFL, 0)) == -1) 
    {   
        SystemFatal("fcntl");
    }
    // Bind to the specified listening port
    memset (&addr, 0, sizeof (struct sockaddr_in));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = htonl(INADDR_ANY);
    addr.sin_port = htons(src_port);
    if (bind (fd_server, (struct sockaddr*) &addr, sizeof(addr)) == -1) 
    {   
        SystemFatal("bind");
    }
    // Listen for fd_news; SOMAXCONN is 128 by default
    if (listen (fd_server, SOMAXCONN) == -1) 
    {   
        SystemFatal("listen");
    }
//--------------------------------------------------------------------------------------------- 
    // Create the epoll file descriptor
    epoll_fd = epoll_create(EPOLL_QUEUE_LEN);
    if (epoll_fd == -1) 
    {   
        SystemFatal("epoll_create");
    }
    // Add the server socket to the epoll event loop
    event.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLET;
    event.data.fd = fd_server;
    if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, fd_server, &event) == -1) 
    {
        SystemFatal("epoll_ctl");
    }   
    // Execute the epoll event loop
    while (TRUE) 
    {
        //struct epoll_event events[MAX_EVENTS];
        num_fds = epoll_wait (epoll_fd, events, EPOLL_QUEUE_LEN, -1);
        if (num_fds < 0) 
        {
            SystemFatal ("Error in epoll_wait!");
        }
        for (i = 0; i < num_fds; i++) 
        {
                // Case 1: Error condition
                if (events[i].events & (EPOLLHUP | EPOLLERR)) 
            {
                    fputs("epoll: EPOLLERR", stderr);
                    //close(events[i].data.fd);
                    continue;
                }
                assert (events[i].events & EPOLLIN);
//-----------------------------------------------------------------------------------------
                // Case 2: Server is receiving a connection request
                if (events[i].data.fd == fd_server) 
            {
                //socklen_t addr_size = sizeof(remote_addr);
                fd_new = accept (fd_server, (struct sockaddr*) &remote_addr, &addr_size);
                if (fd_new == -1) 
                {
                        if (errno != EAGAIN && errno != EWOULDBLOCK) 
                    {
                        perror("accept");
                        }
                        continue;
                }
//------------------------------------------------------------------------------------------------
                // Make the fd_new non-blocking
                if (fcntl (fd_new, F_SETFL, O_NONBLOCK | fcntl(fd_new, F_GETFL, 0)) == -1) 
                {
                    SystemFatal("fcntl");
                }

                // Add the new socket descriptor to the epoll loop
                event.data.fd = fd_new;
                if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, fd_new, &event) == -1) 
                {   
                    SystemFatal ("epoll_ctl");
                }
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                printf(" Remote Address:  %s\n", inet_ntoa(remote_addr.sin_addr));
                //close(fd_new);
                dest_port = FORWARD_PORT;       // Used the default forward port
                // create internal connection
                printf("Trying to create forward socket\n");        
                if ((forwardSD = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
                    perror("Cannot create forward socket.");
                    exit(1);
                }

                printf("Binding...\n");
                bzero((char *)&server_fwd, sizeof(struct sockaddr_in));
                server_fwd.sin_family = AF_INET;
                server_fwd.sin_port = htons(dest_port);
                //host = "192.168.0.10";    
                if ((hp = gethostbyname(host)) == NULL) {
                    printf("Failed to get host name");
                }

                bcopy(hp->h_addr, (char *)&server_fwd.sin_addr, hp->h_length);

                printf("Connecting to interal machine.\n");
                printf("Server Forward Port: %d\n", ntohs(server_fwd.sin_port));
                printf("Server Forward IP: %s\n", inet_ntoa(server_fwd.sin_addr));

                // Connecting to interal machine
                if (connect (forwardSD, (struct sockaddr *)&server_fwd, sizeof(server_fwd)) == -1) {
                    perror("connect failed");
                    exit(1);
                }

                // Add the new socket descriptor to the epoll loop
                event.data.fd = forwardSD;
                if (epoll_ctl (epoll_fd, EPOLL_CTL_ADD, forwardSD, &event) == -1) 
                {   
                    SystemFatal ("epoll_ctl");
                }   
                printf ("Connected: Server: %s\n", hp->h_name);
                forwardSockets[fd_new] = forwardSD;
                internalSockets[forwardSD] = fd_new;
            // end internal connection
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
                continue;
                }
                // Case 3: One of the sockets has read data
                if (!forwardData(events[i].data.fd)) 
            {
                // epoll will remove the fd from its set
                // automatically when the fd is closed
                close (events[i].data.fd);      
            }
        }
    }
    close(fd_server);
    exit (EXIT_SUCCESS);
}
int main (int argc, char **argv)
{
    int i, maxi, nready, bytes_to_read, arg;
    int listen_sd, new_sd, sockfd, client_len, port, maxfd, client[FD_SETSIZE];
    struct sockaddr_in server, client_addr;
    char *bp, buf[BUFLEN];
    ssize_t n;
    fd_set rset, allset;

    switch(argc)
    {
    case 1:
        port = SERVER_TCP_PORT;	// Use the default port
        break;
    case 2:
        port = atoi(argv[1]);	// Get user specified port
        break;
    default:
        fprintf(stderr, "Usage: %s [port]\n", argv[0]);
        exit(1);
    }

    // Create a stream socket
    if ((listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
        SystemFatal("Cannot Create Socket!");

    // set SO_REUSEADDR so port can be resused imemediately after exit, i.e., after CTRL-c
    arg = 1;
    if (setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1)
        SystemFatal("setsockopt");

    // Bind an address to the socket
    bzero((char *)&server, sizeof(struct sockaddr_in));
    server.sin_family = AF_INET;
    server.sin_port = htons(port);
    server.sin_addr.s_addr = htonl(INADDR_ANY); // Accept connections from any client

    if (bind(listen_sd, (struct sockaddr *)&server, sizeof(server)) == -1)
        SystemFatal("bind error");

    // Listen for connections
    // queue up to LISTENQ connect requests
    listen(listen_sd, LISTENQ);

    maxfd	= listen_sd;	// initialize
    maxi	= -1;		// index into client[] array

    for (i = 0; i < FD_SETSIZE; i++)
        client[i] = -1;             // -1 indicates available entry
    FD_ZERO(&allset);
    FD_SET(listen_sd, &allset);


    while (TRUE)
    {
        rset = allset;               // structure assignment
        nready = select(maxfd + 1, &rset, NULL, NULL, NULL);

        if (FD_ISSET(listen_sd, &rset)) // new client connection
        {
            client_len = sizeof(client_addr);
            if ((new_sd = accept(listen_sd, (struct sockaddr *) &client_addr, &client_len)) == -1)
                SystemFatal("accept error");

            printf(" Remote Address:  %s\n", inet_ntoa(client_addr.sin_addr));

            for (i = 0; i < FD_SETSIZE; i++)
                if (client[i] < 0)
                {
                    client[i] = new_sd;	// save descriptor
                    break;
                }
            if (i == FD_SETSIZE)
            {
                printf ("Too many clients\n");
                exit(1);
            }

            FD_SET (new_sd, &allset);     // add new descriptor to set
            if (new_sd > maxfd)
                maxfd = new_sd;	// for select

            if (i > maxi)
                maxi = i;	// new max index in client[] array

            if (--nready <= 0)
                continue;	// no more readable descriptors
        }

        for (i = 0; i <= maxi; i++)	// check all clients for data
        {
            if ((sockfd = client[i]) < 0)
                continue;

            if (FD_ISSET(sockfd, &rset))
            {
                bp = buf;
                bytes_to_read = BUFLEN;
                while ((n = read(sockfd, bp, bytes_to_read)) > 0)
                {
                    bp += n;
                    bytes_to_read -= n;
                }
                write(sockfd, buf, BUFLEN);   // echo to client

                if (n == 0) // connection closed by client
                {
                    printf(" Remote Address:  %s closed connection\n", inet_ntoa(client_addr.sin_addr));
                    close(sockfd);
                    FD_CLR(sockfd, &allset);
                    client[i] = -1;
                }

                if (--nready <= 0)
                    break;        // no more readable descriptors
            }
        }
    }
    return(0);
}
/*------------------------------------------------------------------------------------------------------------------
-- FUNCTION: startServer
--
-- DATE: March 14, 2014
--
-- REVISIONS: March 16 - added printing users list and users quitting
--            March 17 - added messaging specific users
--            March 20 - added role based users
--
-- DESIGNER: Damien Sathanielle
--
-- PROGRAMMER: Damien Sathanielle
--
-- INTERFACE: void startServer(
--                             int port - port number for server
--                             )
--
-- RETURNS: void
--
-- NOTES: The server will run in a forever loop checking and updating connections using select()
--        Special commands such as kicking a user and promoting a user are also handled by the server
--
------------------------------------------------------------------------------------------------------------------*/
void startServer(int port)
{
    char serverName[BUFLEN];
    printf("Please enter a server name: \n");
    fgets(serverName, BUFLEN, stdin);

    signal(SIGINT, catch_int_server);

    int  listen_sd, new_sd, sockfd,
         maxfd,
         maxi,
         bytes_to_read,
         i, j, k,
         promotion,
         nready,
         lengthOfClientName;

    char sbuf[BUFLEN],
        *bp,
         buf[BUFLEN],
         msgUser[30],
         ctrlCharacter1,
         ctrlCharacter2,
         ctrlCharacter3,
         clientName[BUFLEN];

    socklen_t client_len;

    struct sockaddr_in server, client_addr;

    ssize_t n;
    fd_set rset, allset;
    printf("Server name: %s", serverName);
    printf("Server listening on port: %d\n", port);

    listen_socket(&listen_sd, &server, port);

    if (bind(listen_sd, (struct sockaddr *)&server, sizeof(server)) == -1)
        SystemFatal("bind error");

    listen(listen_sd, LISTENQ);

    maxfd = listen_sd;
    maxi = -1;
    numClients = 0;

    for(i = 0; i < FD_SETSIZE; i++)
        client[i] = -1;
    FD_ZERO(&allset);
    FD_SET(listen_sd, &allset);
    /* set sockets in client struct to -1 */
    for(i = 0; i < MAX_CLIENTS; i++)
        client_list[i].socket = -1;


    while(1)
    {
        memset(buf, 0, BUFLEN);
        rset = allset;               // structure assignment
        nready = select(maxfd + 1, &rset, NULL, NULL, NULL);

        if (FD_ISSET(listen_sd, &rset)) // new client connection
        {
            client_len = sizeof(client_addr);
            if ((new_sd = accept(listen_sd, (struct sockaddr *) &client_addr, &client_len)) == -1)
                SystemFatal("accept error");

            bp = buf;
            read(new_sd, bp, BUFLEN);
            sscanf(bp, "%c %c %d %s %c", &ctrlCharacter1, &ctrlCharacter2, &lengthOfClientName, clientName, &ctrlCharacter3);



            for (i = 0; i < FD_SETSIZE; i++)
            {
                if (client[i] < 0)
                {
                    client[i] = new_sd;    // save descriptor

                    printf("%s has connected with the remote address of %s\n", clientName, inet_ntoa(client_addr.sin_addr));
                    // send server name
                    memset(sbuf, 0, BUFLEN);
                    sprintf(sbuf, "%c %c %zu %s %c", SYN, 0x03, strlen(serverName), serverName, EOT);
                    write(client[i], sbuf, BUFLEN);

                    for(j = 0; j < MAX_CLIENTS; j++)
                    {
                        if(client_list[j].socket == -1)
                        {
                            if(numClients == 0)
                                addClient(j, i, 'a', clientName, inet_ntoa(client_addr.sin_addr));
                            else
                                addClient(j, i, 'n', clientName, inet_ntoa(client_addr.sin_addr));
                            break;
                        }
                    }

                    break;
                }
            }
            if (i == FD_SETSIZE)
            {
                printf ("Too many clients\n");
                exit(1);
            }

            memset(sbuf, 0, BUFLEN);
            strcat(sbuf, inet_ntoa(client_addr.sin_addr));
            strcat(sbuf, " ");
            strcat(sbuf, clientName);
            strcat(sbuf, " joined the chat channel.\n");

            /* notify other users that a new user has joined the chat */
            for(j = 0; j <= maxfd; j++)
            {
                if(client[j] < 0)
                    continue;
                if(client[j] == new_sd)
                    continue;
                write(client[j], sbuf, BUFLEN);
            }


            FD_SET (new_sd, &allset);     // add new descriptor to set


            if (new_sd > maxfd)
                maxfd = new_sd;    // for select

            if (i > maxi)
                maxi = i;    // new max index in client[] array

            if (--nready <= 0)
                continue;    // no more readable descriptors
        }

        for (i = 0; i <= maxi; i++)    // check all clients for data
        {
            if ((sockfd = client[i]) < 0)
                continue;

            if (FD_ISSET(sockfd, &rset))
            {
                bp = buf;
                bytes_to_read = BUFLEN;

                while ((n = read(sockfd, bp, bytes_to_read)) > 0)
                {
                    bp += n;
                    bytes_to_read -= n;
                }
                /* displays list of current users and their status */
                if(strstr(buf, "/users"))
                {
                    for(k = 0; k < MAX_CLIENTS; k++)
                    {
                        if(client_list[k].socket > -1)
                        {
                            for(j = 0; j <= maxfd; j++)
                            {
                                if(j == i)
                                {
                                    sprintf(buf, "%c", client_list[k].role);
                                    strcat(buf, " ");
                                    strcat(buf, client_list[k].username);
                                    strcat(buf,"\n");
                                    write(client[j], buf, BUFLEN);
                                }
                            }
                        }
                    }
                    sprintf(buf, "%d", numClients);
                    strcat(buf, " users in chat.\n\n");
                    write(client[i], buf, BUFLEN);
                    break;
                }

                if(strstr(buf, "/msg"))
                {
                    strcpy(msgUser, getName(buf));
                    trim(msgUser);
                    for(k = 0; k < MAX_CLIENTS; k++)
                    {
                        if((client_list[k].socket > -1) && !strcmp(client_list[k].username, msgUser))
                        {
                            for(j = 0; j <= maxfd; j++)
                            {
                                if(j == client_list[k].socket)
                                    write(client[j], buf, BUFLEN);
                            }
                        }
                    }
                    break;
                }

                if(strstr(buf, "/kick"))
                {
                    if(check_permission(i))
                    {
                        buf[strlen(buf) - 1] = 0;
                        strcpy(msgUser, getName(buf));
                        trim(msgUser);
                        for(k = 0; k < MAX_CLIENTS; k++)
                        {
                            if((client_list[k].socket > -1) && !strcmp(client_list[k].username, msgUser))
                            {
                                for(j = 0; j <= maxfd; j++)
                                {
                                    if(j == client_list[k].socket)
                                    {
                                        write(client[j], "you have been kicked\n", BUFLEN);
                                        removeClient(j);
                                        client[j] = -1;
                                    }
                                }
                            }
                        }
                        break;
                    }else
                        write(client[i], "you don't have permission\n", BUFLEN);
                }
                /* promote a user to admin or remove admin status from user */
                if(strstr(buf, "/promote") || strstr(buf, "/demote"))
                {
                    if(check_permission(i))
                    {
                        if(strstr(buf, "/promote"))
                            promotion = 1;
                        else
                            promotion = 0;

                        buf[strlen(buf) - 1] = 0;
                        strcpy(msgUser, getName(buf));
                        trim(msgUser);
                        for(k = 0; k < MAX_CLIENTS; k++)
                        {
                            if((client_list[k].socket > -1) && !strcmp(client_list[k].username, msgUser))
                            {
                                for(j = 0; j <= maxfd; j++)
                                {
                                    if(j == client_list[k].socket)
                                    {
                                        if(promotion)
                                        {
                                            client_list[j].role = 'a';
                                            write(client[j], "you have been promoted!!\n", BUFLEN);
                                        }else
                                        {
                                            client_list[j].role = 'n';
                                            write(client[j], "you have been demoted\n", BUFLEN);
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    }else
                        write(client[i], "you don't have permission\n", BUFLEN);
                }
                /* disconnected signal */
                if(strstr(buf, "has left the chat"))
                {
                    for(j = 0; j <= maxfd; j++)
                    {
                        if(j == i)
                        {
                            removeClient(j);
                            client[i] = -1;
                        }

                        else
                            write(client[j], buf, BUFLEN);
                    }
                    break;
                }

                /* if users enters invalid command */
                if(strstr(buf, "/"))
                {
                    write(client[i], "type /help for a list of commands\n", BUFLEN);
                }else
                {
                    for(j = 0; j <= maxfd; j++)
                    {
                        if(j != i)
                            write(client[j], buf, BUFLEN);
                    }
                }

                if (--nready <= 0)
                    break;        // no more readable descriptors
            }
        }
    }
    close(sockfd);
    exit(0);
}
int main() {
	int nready, maxfd, arg;
	int maxi = -1;
	int listen_sd, new_sd = 0;
	int port = SERVER_TCP_PORT;
	pthread_t clientThread;
	socklen_t client_len = 0;
	struct sockaddr_in server, client_addr;
	fd_set rset;
	i = 0;
	connected = 0;
	
	if ((listen_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
		perror ("Can't create a socket");
		exit(1);
	}

	arg = 1;
    if (setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1) {
		perror("SetSockOpt Failed!");
		exit(1);
    }

	bzero((char *)&server, sizeof(struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	server.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(listen_sd, (struct sockaddr *)&server, sizeof(server)) == -1) {
		perror("Can't bind name to socket");
		exit(1);
	}

	listen(listen_sd, LISTENQ);
	maxfd = listen_sd;
	maxi = -1;

	for (i = 0; i < FD_SETSIZE; i++) client[i] = -1;

	FD_ZERO(&allset);
	FD_SET(listen_sd, &allset);
	

	while(TRUE) {
		rset = allset;
		nready = select(maxfd + 1, &rset, NULL, NULL, NULL);
		
		if (FD_ISSET(listen_sd, &rset)) {
			client_len = sizeof(client_addr);
			if ((new_sd = accept(listen_sd, (struct sockaddr *)&client_addr, &client_len)) == -1)
				SystemFatal("accept error");
			
			connected++;
			printf("Currently serving %d connections...\n", connected);

			for (i = 0; i < FD_SETSIZE; i++) {
				if (client[i] < 0) {
					client[i] = new_sd;
					break;
				}
			}
			if (i == FD_SETSIZE) {
				printf("Too many clients :/\n");
				exit(1);
			}
			FD_SET(new_sd, &allset);
			if (new_sd > maxfd)
                maxfd = new_sd; // for select
            if (i > maxi)
                maxi = i;   // new max index in client[] array
            if (--nready <= 0)
                continue;   // no more readable descriptors
		}
		ClientData *aClient;
		aClient = malloc(sizeof(ClientData));
		aClient->client = &client[i];
		aClient->sockfd = sockfd;
		aClient->nready = nready;
		aClient->maxi = maxi;
		aClient->rset = rset;
		aClient->allset = allset;
		aClient->ipAddr = inet_ntoa(client_addr.sin_addr);
		aClient->port = client_addr.sin_port;
		pthread_create(&clientThread, NULL, ioworker, (void*)aClient);	
		pthread_detach(clientThread);
		// ioworker(client, sockfd, nready, maxi, rset, allset);
		// printf("Breakpoint 1");
	}
	close(listen_sd);
	return EXIT_SUCCESS;
}
Example #12
0
int main (int argc, char **argv)
{
	int n, bytes_to_read;
	int sd, server_port, ret;
	char  *host, *bp, rbuf[BUFLEN], sbuf[BUFLEN];
	struct sockaddr_in6 client, client2; 
  	char ip6str[INET6_ADDRSTRLEN];
	
	switch (argc)
	{
		case 1:
			host = DEFAULT_HOST;	//Default host name
			server_port = SERVER_TCP_PORT;	//Default port
		break;
		case 2:
			host =	argv[1];	// Host name
			server_port = SERVER_TCP_PORT; //use default port
		break;
		case 3:
			host =	argv[1];
			server_port = atoi(argv[2]);	// User specified port
		break;
		default:
			printf ("Using default host: %s  port: %d\n", DEFAULT_HOST, SERVER_TCP_PORT);
	}
		
	memset (&client2, 0, sizeof(client2)); 

	client2.sin6_family = AF_INET6;
	ret = inet_pton (AF_INET6,host,&(client2.sin6_addr));	

	client2.sin6_port = htons (server_port);

	printf ("\nSend the string \"server-halt\" to shut the server down\n");
	printf ("\nConnecting to %s = %s (err=%d)\n", host, inet_ntop(AF_INET6,&client.sin6_addr,ip6str,sizeof(ip6str)),ret);
	printf ("Same as %s\n",inet_ntop(AF_INET6,&client2.sin6_addr,ip6str,sizeof(ip6str)));

	// Create the socket
	if ((sd = socket (AF_INET6, SOCK_STREAM,0)) == -1)
		SystemFatal ("Cannot create socket");
   	
	
	// Connecting to the server
	if (connect (sd,(void *)&client2, sizeof(client2)) == -1)
		SystemFatal ("Can't connect to server");
   	
	printf("\nTransmit: ");
	fgets (sbuf, BUFLEN, stdin);

	// Transmit data through the socket
	send (sd, sbuf, BUFLEN, 0);

	printf("Receive: ");
	bp = rbuf;
	bytes_to_read = BUFLEN;

	// client makes repeated calls to recv until no more data is expected to arrive.
	n = 0;
	while ((n = recv (sd, bp, bytes_to_read, 0)) < BUFLEN)
	{
		bp += n;
		bytes_to_read -= n;
	}
	printf ("%s\n", rbuf);
	fflush(stdout);
	close (sd);
	return (0);
}
Example #13
0
/**
 * read_from_client
 *
 * Handles the activities that take place on the sockets monitored by
 * select. The activity includes new connections or data transfer from
 * existing connections.
 *
 * @param s Server struct, contains information about the server.
 */
void read_from_socket(server *s) {
	//int ret, maxi;
	client *c = NULL;
	node *n = NULL;

	//maxi = 0;

	/* Check if a client is trying to connect */
	pthread_mutex_trylock(&s->dataLock);
	if (FD_ISSET(s->listen_sd, &s->allset)) {

		/* get the client data ready */
		c = client_new();

		/* blocking call waiting for connections */
		c->fd = accept(s->listen_sd, (struct sockaddr *) &c->sa, &c->sa_len);
		/* make the client Socket non-blocking */
		if (fcntl(c->fd, F_SETFL, O_NONBLOCK | fcntl(c->fd, F_GETFL, 0)) == -1)
			SystemFatal("fcntl(): Client Non-Block Failed\n");

		fprintf(stdout, "Received connection from (%s, %d)\n",
			inet_ntoa(c->sa.sin_addr),
			ntohs(c->sa.sin_port));
		s->n_clients++;
		s->n_max_connected++;
		/*s->n_max_connected = (s->n_clients > s->n_max_connected) ?
				s->n_clients : s->n_max_connected;*/
		s->client_list = llist_append(s->client_list, (void *)c);
		fprintf(stdout, "Added client to list, new size: %d\n",
			llist_length(s->client_list));
		/* add the client to the list */
		/*for (i = 0; i < FD_SETSIZE; i++) {
			if (s->clientConn[i] == NULL) {
			s->clientConn[i] = c;
			//break;
			}
			if (s->clients[i] < 0) {
			s->clients[i] = c->fd;
			break;
			}
			if (i == FD_SETSIZE) {
			SystemFatal("To Many Clients\n");
			}
			}*/
		/* add the socket connections to the fd_set */
		/*FD_SET(c->fd, &s->allset);
		s->maxfd = (c->fd > s->maxfd) ?
		c->fd : s->maxfd;
		maxi = (i > maxi) ? i : maxi;*/
		c = NULL;
	}
	pthread_mutex_unlock(&s->dataLock);

	for (n = s->client_list->link; n != NULL; n = n->next) {

		/* check if the client cause an event */
		pthread_mutex_trylock(&s->dataLock);
		c = (client *)n->data;
		if (FD_ISSET(c->fd, &s->allset)) {
			process_client_req(c, s);
			//process_client_data(c, s);
		}
		pthread_mutex_unlock(&s->dataLock);

		//pthread_mutex_trylock(&s->dataLock);  TRY THIS LATER
		if (c->quit) {
			pthread_mutex_trylock(&s->dataLock);
			s->n_clients--;
			s->client_list = llist_remove(s->client_list, (void *)c, client_compare);
			fprintf(stderr, "[%5d]Removed client from list, new size: %d\n",
				c->fd, llist_length(s->client_list));
			close(c->fd);
			free(c);
			c = NULL;
			pthread_mutex_unlock(&s->dataLock);
		}
		//pthread_mutex_unlock(&s->dataLock);  TRY THIS LATER
	}

	/* go through the available connections */
	/*for(n = 0; n <= maxi; n++) {
		pthread_mutex_trylock(&s->dataLock);
		if(FD_ISSET(s->clients[n], &s->allset)){
		process_client_data();
		}
		pthread_mutex_unlock(&s->dataLock);
		}*/
	//free(c);
}
/*---------------------------------------------------------------------------------------
-- FUNCTION: run_server
--
-- DATE: February 11, 2016
--
-- DESIGNERS: Rizwan Ahmed, Vishav Singh
--
-- PROGRAMMERS: Rizwan Ahmed, Vishav Singh
--
-- PARAMETERS: 
--   int serv_port - the server socket's port number
--
-- RETURNS: 0 on exit
--
-- NOTES: Sets up sockets and uses select() to handle connections.
---------------------------------------------------------------------------------------*/
void* run_server(int serv_port)
{
	gettimeofday (&start, NULL);

	//start recording live stats
	pthread_create(&tm, NULL, live_stats, NULL);

	int i, maxi, nready, arg, t;
	int listen_sd, new_sd, sockfd, maxfd, client[FD_SETSIZE];
	struct sockaddr_in server, client_addr;
	char buf[BUFFER];
	ssize_t n;
	fd_set rset, allset;
	socklen_t client_len;
	int port = serv_port; // Use the default port
	
	//SOCKET OPTIONS for LINGER
        struct linger linger;
        memset(&linger,0,sizeof(linger));
        linger.l_onoff = 1;
        linger.l_linger = 0;

	//create the socket
	if ((listen_sd = socket(AF_INET, SOCK_STREAM,0))== -1)
	SystemFatal("Cannot create socket!");

	// set SO_REUSEADDR so port can be resused imemediately after exit, i.e., after CTRL-c
	arg = 1;
	if (setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) == -1)
	SystemFatal("setsockopt");

	// Bind an address to the socket
	bzero((char *) &server, sizeof (struct sockaddr_in));
	server.sin_family = AF_INET;
	server.sin_port = htons(port);
	server.sin_addr.s_addr = htonl(INADDR_ANY); // Accept connections from any client

	if (bind(listen_sd, (struct sockaddr *) &server, sizeof (server)) == -1)
	SystemFatal("bind error");


	// Listen for connections
	// queue up to LISTENQ connect requests
	listen(listen_sd, MAX_CLIENTS);

	//set the socket to non-blocking
	fcntl(listen_sd, F_SETFL, O_NONBLOCK, 0);
	
        //Set SOCKET OPTION LINGER
        if(setsockopt(listen_sd, SOL_SOCKET, SO_LINGER,(char*)&linger, sizeof(linger)) == -1)
        {
                SystemFatal("Failed while setting SOCKET Options: SO_LINGER");
        }
        
	maxfd = listen_sd; // initialize
	maxi = -1; // index into client[] array

	for (i = 0; i < FD_SETSIZE; i++)
	client[i] = -1; // -1 indicates available entry
	FD_ZERO(&allset);
	FD_SET(listen_sd, &allset);

		ClntStats * clnt_stats;

		while (1) {
			rset = allset; // structure assignment
			nready = select(maxfd + 1, &rset, NULL, NULL, NULL);

			if (FD_ISSET(listen_sd, &rset)){ // new client connection
				client_len = sizeof (client_addr);
				if ((new_sd = accept(listen_sd, (struct sockaddr *) &client_addr, &client_len)) == -1)
				SystemFatal("accept error");

				for (i = 0; i < FD_SETSIZE; i++)
				if (client[i] < 0) {
					client[i] = new_sd; // save descriptor
					break;
				}
				if (i == FD_SETSIZE) {
					printf("Too many clients\n");
					exit(1);
				}

				FD_SET(new_sd, &allset); // add new descriptor to set
				if (new_sd > maxfd)
				maxfd = new_sd; // for select

				if (i > maxi)
				maxi = i; // new max index in client[] array

				// Get new client stats
				char * ip_address = inet_ntoa(client_addr.sin_addr);
				//printf("CONNECTED TO: %s\n",ip_address);
				if((clnt_stats = get_stats(ip_address)) == NULL)
				SystemFatal("get_stats");
				clnt_stats->total_connect++;
				clnt_stats->curr_connect++;

				if (--nready <= 0)
				continue; // no more readable descriptors
			}

			for (i = 0; i <= maxi; i++) // check all clients for data
			{
				if ((sockfd = client[i]) < 0)
				continue;

				if (FD_ISSET(sockfd, &rset)) {
					n = read(sockfd, buf, BUFFER);
					if (n == BUFFER) {
						write(sockfd, buf, BUFFER); // echo to client
						// Get client's sockaddr_in
						struct sockaddr addr;
						socklen_t size = sizeof(struct sockaddr);
						if((getpeername(sockfd, &addr, &size)) == -1){
							SystemFatal("getpeername");
						}

						struct sockaddr_in * sin;
						if(addr.sa_family == AF_INET){
							sin = (struct sockaddr_in *)&addr;
						}
						else
						SystemFatal("not ip4");

						// Get client stats
						char * ip_address = inet_ntoa(sin->sin_addr);
						if((clnt_stats = get_stats(ip_address)) == NULL)
						SystemFatal("get_client_stats");
						clnt_stats->message++;
						clnt_stats->total_message++;
						clnt_stats->curr_data += n;
						clnt_stats->total_data += n;

					}

					if (n == 0) // connection closed by client
					{
						close(sockfd);
						FD_CLR(sockfd, &allset);
						client[i] = -1;
						t++;
					}
					if (n == -1) {
						if (errno == EAGAIN || errno == EWOULDBLOCK) {
						} else {
							perror("read fail");
						}
					}
				}
			}
		}
	}