/** * 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; }
/** * 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); }
/** * 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); }
/** * 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); }
/** * 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; }
/** * 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; } }
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; }
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); }
/** * 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"); } } } } } }