Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- Basic non-blocking TCP/IP Chat Server Source Code
- * Copyright (c) 2014 JUAN JOSE FERNANDEZ LOPEZ
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- Contact: Current Cel & email - 7873973266 - jjfl.88@aol.com
- Example client: $ nc serverhosturlorip 6660 [enter]
- INPUT: myname [enter]
- INPUT: THE MESSAGE [enter]
- OUTPUT: myname> THE MESSAGE
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <unistd.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <netinet/in.h>
- #include <netinet/tcp.h>
- #include <arpa/inet.h>
- #include <poll.h>
- #include <signal.h>
- #include <time.h>
- #include <fcntl.h>
- #include <netdb.h>
- #define PORT 6660
- struct pollfd *fds;
- /* used to record client information */
- typedef struct {
- int fd;
- char name[260];
- _Bool nameset:1;
- } client;
- client *clnt;
- /* set-up ipv4 address */
- void setipv4address(struct sockaddr_in * serv_addr)
- {
- serv_addr[0].sin_family = AF_INET;
- serv_addr[0].sin_addr.s_addr = INADDR_ANY;
- serv_addr[0].sin_port = htons((uint16_t)PORT);
- }
- /* signal handling */
- void terminate(int n) {
- free(fds);
- free(clnt);
- exit(n);
- }
- int main(void)
- {
- /* BSD DAEMON */
- void daemonize();
- void setipv4address(struct sockaddr_in *);
- void terminate(int);
- int sockfd,i,read_val,msglen,seconds;
- int tcp_protocol_number = (getprotobyname("tcp"))->p_proto;
- char buff[256];
- char msg[500];
- nfds_t nfds,x;
- int on;
- socklen_t cli_addr_len;
- struct sockaddr_in serv_addr, cli_addr;
- daemonize();
- cli_addr_len = sizeof(cli_addr);
- sockfd = socket(AF_INET, SOCK_STREAM, 0);
- seconds=25;
- on=1;
- signal(SIGINT,terminate);
- signal(SIGTERM,terminate);
- signal(SIGPIPE,SIG_IGN);
- setipv4address(&serv_addr);
- if((bind(sockfd, (struct sockaddr *) &serv_addr,sizeof(serv_addr))) == -1)
- {
- exit(EXIT_FAILURE);
- }
- if((listen(sockfd,5)) == -1) {
- exit(EXIT_FAILURE);
- }
- nfds = 1;
- if(!(clnt = (client *) calloc (1,nfds * sizeof(client))))
- {
- perror("ERROR: ");
- exit(EXIT_FAILURE);
- }
- if(!(fds = (struct pollfd *) calloc(1,nfds * sizeof(struct pollfd))))
- {
- perror("ERROR: ");
- exit(EXIT_FAILURE);
- }
- fds[0].fd = sockfd;
- fds[0].events = POLLIN;
- clnt[0].fd = sockfd;
- clnt[0].name[0]='\0';
- while(1) {
- poll(fds,nfds,-1);
- for(i=0; (i < (int) nfds); ++i)
- {
- if( !i && (fds[i].revents & POLLIN) ) {
- clnt = (client *) realloc(clnt,((nfds+1) * sizeof(client)));
- fds = (struct pollfd *) realloc(fds, ((nfds+1) * sizeof(struct pollfd)));
- if((fds[nfds].fd = accept(sockfd,(struct sockaddr *) &cli_addr, &cli_addr_len)) != -1)
- {
- if( (fcntl(fds[nfds].fd,F_SETFL,O_NONBLOCK)) == -1) {
- perror("fcntl() = -1: ");
- }
- #ifdef TCP_KEEPIDLE
- if((setsockopt(fds[nfds].fd,tcp_protocol_number,TCP_KEEPIDLE,&seconds,sizeof(seconds))) == -1) {
- perror("setsockopt() == -1 1: ");
- }
- #endif
- if((setsockopt(fds[nfds].fd,SOL_SOCKET,SO_KEEPALIVE,&on,sizeof(on))) == -1) {
- perror("setsockopt() == -1 2: ");
- }
- fds[nfds].events = POLLRDNORM;
- clnt[nfds].nameset = 0;
- clnt[nfds].fd = fds[nfds].fd;
- }
- else
- {
- free(fds);
- free(clnt);
- perror("ERROR> -1 on accept(): ");
- exit(EXIT_FAILURE);
- }
- ++nfds;
- }
- else if( fds[i].revents & (POLLNVAL | POLLHUP | POLLERR) ) {
- if(!(fds[i].events & POLLNVAL)) {
- close(fds[i].fd);
- }
- --nfds;
- if((nfds - i) == 0) {
- x=1;
- }
- else {
- x=nfds-1;
- }
- memcpy((&(clnt[i])), (&(clnt[i+1])),sizeof(clnt) * (x));
- memcpy( (&(fds[i])), (&(fds[i+1])),sizeof(struct pollfd) * (x));
- fds = (struct pollfd *) realloc( fds, ( nfds * (sizeof(struct pollfd)) ) );
- clnt = (client *) realloc( clnt, ( nfds * (sizeof(client)) ) );
- }
- else if( (i != 0) && (fds[i].revents & POLLRDNORM) ) {
- read_val = read(fds[i].fd,buff,255);
- buff[read_val] = '\0';
- if(read_val <= 0) {
- if(!(read_val)) {
- close(fds[i].fd);
- }
- --nfds;
- if((nfds - i) == 0) {
- x=1;
- }
- else {
- x=nfds-1;
- }
- memcpy( (&(clnt[i])), (&(clnt[i+1])),sizeof(client) * (x));
- memcpy( (&(fds[i])), (&(fds[i+1])), sizeof(struct pollfd) * (x));
- fds = (struct pollfd *) realloc( fds, ( nfds * (sizeof(struct pollfd)) ) );
- clnt = (client *) realloc( clnt, ( nfds * (sizeof(client)) ) );
- }
- else {
- if((clnt[i].nameset)) {
- x=1;
- msg[0]='\0';
- strcat(msg,clnt[i].name);
- strcat(msg,"> ");
- strcat(msg,buff);
- msglen=strlen(msg);
- while(x < nfds)
- {
- write(clnt[x].fd,msg,msglen);
- ++x;
- }
- }
- else {
- clnt[i].nameset = 1;
- clnt[i].name[0] = '\0';
- if(buff[(strlen(buff))-1] == '\n') {
- buff[(strlen(buff))-1] = '\0';
- }
- strcat(clnt[i].name,buff);
- }
- }
- }
- }
- }
- /*
- Flow never reach here
- */
- free(fds);
- free(clnt);
- return 0;
- }
- void daemonize()
- {
- pid_t pid; /* PROCESS ID */
- pid_t sid; /* SESSION ID (SAME AS PID) */
- pid = fork(); /* NEW CHILD */
- if (pid < 0) /* ERROR HANDLING */
- exit(EXIT_FAILURE);
- if (pid > 0)
- exit(EXIT_SUCCESS); /* SAY BYEBYE TO FATHER */
- umask(0); /* TO BE SURE WE HAVE ACCESS TO ANY GENERATED FILE FROM DAEMON */
- sid = setsid(); /* WE OWN OUR OWN PLACE */
- if (sid < 0) /* ERROR HANDLING */
- exit(EXIT_FAILURE);
- if((chdir("/")) < 0) /* CHANGE TO A PATH THAT WILL ALWAYS BE THERE */
- exit(EXIT_FAILURE);
- close(STDIN_FILENO); /* CLOSE STANDARD INPUT */
- close(STDOUT_FILENO); /* CLOSE STANDARD OUTPUT */
- close(STDERR_FILENO); /* CLOSE STANDARD ERROR OUTPUT */
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement