All pastes #822358 Raw Edit

Something

public text v1 · immutable
·published 2007-12-18 18:13 UTC
rendered paste body
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define PORT 7989   // port we're listening on
#define SHOW 1      // command show
#define MESSAGE 2
#define HELP 3
#define NICK 4
#define NEWLINE 5



void write_to_socket(int target,char *buff_to_send,int len);
int check_for_command(char *buffer,int *p);
int is_fd_valid(int destination) ;
void type_writer(char *buf,int len,int fd);
typedef struct
{
  int id;  /* socket descripter */
  char nick[30]; /* store the nick here */
  short flag_nick;
}USER;


USER user[20];
int usercount=0;

int main(void)
{
  fd_set master;   // master file descriptor list
  fd_set read_fds; // temp file descriptor list for select()
  struct sockaddr_in myaddr;     // server address
  struct sockaddr_in remoteaddr; // client address
  int fdmax;        // maximum file descriptor number
  int listener;     // listening socket descriptor
  int newfd;        // newly accept()ed socket descriptor
  char buf[1024];    // buffer for client data
  int nbytes;
  int yes=1;        // for setsockopt() SO_REUSEADDR, below
  int addrlen;
  int i, j,k,tmp,destination=0;
  int str_len;
  char c;
  char *tmp_ptr;
  //USER user[20];
  //int usercount=0;
  bzero(user,sizeof(USER));

  FD_ZERO(&master);    // clear the master and temp sets
  FD_ZERO(&read_fds);

  // get the listener
  if ((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
    perror("socket");
    exit(1);
  }

  // lose the pesky "address already in use" error message
  if (setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &yes,
	sizeof(int)) == -1) {
    perror("setsockopt");
    exit(1);
  }

  // bind
  myaddr.sin_family = AF_INET;
  myaddr.sin_addr.s_addr = INADDR_ANY;
  myaddr.sin_port = htons(PORT);
  memset(&(myaddr.sin_zero), '\0', 8);
  if (bind(listener, (struct sockaddr *)&myaddr, sizeof(myaddr)) == -1) {
    perror("bind");
    exit(1);
  }

  // listen
  if (listen(listener, 10) == -1) {
    perror("listen");
    exit(1);
  }

  // add the listener to the master set
  FD_SET(listener, &master);

  // keep track of the biggest file descriptor
  fdmax = listener; // so far, it's this one

  // main loop
  for(;;) {
    read_fds = master; // copy it
    if (select(fdmax+1, &read_fds, NULL, NULL, NULL) == -1) {
      perror("select");
      exit(1);
    }

    // run through the existing connections looking for data to read
    for(i = 0; i <= fdmax; i++) {
      if (FD_ISSET(i, &read_fds)) { // we got one!!
	if (i == listener) {
	  // handle new connections
	  addrlen = sizeof(remoteaddr);
	  if ((newfd = accept(listener, (struct sockaddr *)&remoteaddr,
		  &addrlen)) == -1) { 
	    perror("accept");
	  } else {
	    FD_SET(newfd, &master); // add to master set
	    if (newfd > fdmax) {    // keep track of the maximum
	      fdmax = newfd;
	    }
	    user[usercount].id=newfd;
	    ++usercount;
	    printf("selectserver: new connection from %s on "
		"socket %d\n", inet_ntoa(remoteaddr.sin_addr), newfd);
	    bzero(buf,sizeof(buf));
	    strcpy(buf,"\n\n\n\n\n\n\n\n\n\n\n********************************************************************************\n");
	    str_len=strlen(buf);
	    write_to_socket(newfd,buf,str_len);

	    
	    bzero(buf,sizeof(buf));
	    strcpy(buf,"\n\n\t\t\tWelcome to AnKiChaTTEr chat server\n\n\n");
	    str_len=strlen(buf);
	    type_writer(buf,str_len,newfd);
	    
	    bzero(buf,sizeof(buf));
	    strcpy(buf,"********************************************************************************\n\n"
		"\t\t\t~Type /SHOW/ to list all online users\n\n"
		"\t~ To send a message to everyone in the room just type the message and press enter\n\n"
		"\t\t~ Type /numeric-user/ to send a message to particular user only\n\n"
		"\t\t ex: /6/ Hi number 6 how r u\n\n"
		"\t\t\t~ Type /HELP/ to see server commands\n\n\n"
		"********************************************************************************\n\n\n\n>>" );
	    str_len=strlen(buf);
	    write_to_socket(newfd,buf,str_len);
	    
	    //strcpy(buff,"\tWelecome to Ank's chat server\n");
	  }
	} else {
	  // handle data from a client
	  if ((nbytes = recv(i, buf, sizeof(buf), 0)) <= 0) {
	    // got error or connection closed by client
	    if (nbytes == 0) {
	      // connection closed
	      printf("selectserver: socket %d hung up\n", i);
	    } else {
	      perror("recv");
	    }
	    close(i); // bye!
	    FD_CLR(i, &master); // remove from master set
	  } else {
	    // we got some data from a client
	    //printf("\n%s\n",buf);
	    for(j = 0; j <= fdmax; j++) {
	      // send to everyone!
	      if (FD_ISSET(j, &master)) {
		// except the listener and ourselves
		if (j != listener && j != i) {
		  switch(check_for_command(buf,&destination))
		  {
		    case SHOW: 
		      //strcpy(buf,"Got the command request :-)\n>>\r\n" );
		      //str_len=strlen(buf);
		      k= usercount-1;
		      bzero(buf,sizeof(buf));
		      while(k>=0)
		      {

			sprintf(buf,"<%d>\n>>",user[k].id);
			str_len=strlen(buf);
			write_to_socket(i,buf,str_len);
			--k;
		      }

		      j=1111; // to end the loop
		      break;
		    case MESSAGE:
		      if( is_fd_valid(destination) )
		      {
			tmp_ptr=buf;
			while(*tmp_ptr==' ')
			  ++tmp_ptr;
			c=destination;
			*(tmp_ptr+1)=i+'0';//(char)destination;
			tmp_ptr=strchr(buf,'\n');
			//str_len=strlen(buf);
			write_to_socket(destination,buf,tmp_ptr-buf+1);

			printf("\nGood show\n");
		      }
		      else
		      {
			bzero(buf,sizeof(buf));
			strcpy(buf,"Invalid user\n>>\r\n");
			str_len=strlen(buf);
			write_to_socket(i,buf,str_len);
		      }
		      j=1111; // to end the loop
		      break;

		    case HELP:
		      bzero(buf,sizeof(buf));
		      strcpy(buf,"\n\n\n********************************************************************************\n\n\n"
			  "\t\t\t~Type /SHOW/ to list all online users\n\n"
			  "\t~ To send a message to everyone in the room \n"
			  "\t\t\tjust type the message and press enter\n\n"
			  "\t\t~ Type /numeric-user/ to send a message to particular user only\n\n"
			  "\t\t\t\t ex: /6/ Hi number 6 how r u\n\n"
			  "\t\t\t~ Type /HELP/ to see server commands\n\n\n>>"
			  "********************************************************************************\n\n\n\n>>" );
		      str_len=strlen(buf);
		      write_to_socket(newfd,buf,str_len);

		        j=1111;
			break;
		    case NEWLINE:
			bzero(buf,sizeof(buf));
			sprintf(buf,">>");
			//str_len=strlen(buf);
			write_to_socket(i,buf,strlen(buf));
			j=1111;
			break;
		    case NICK:
			//printf("Got the nick\n");
			//bzero(buf,sizeof(buf));
			tmp_ptr=buf;
			tmp_ptr+=6;
			for(tmp=0;tmp<fdmax;++tmp)
			{
			  if(user[tmp].id==i)
			    break;
			}
			user[tmp].flag_nick=1;
			strncpy(user[tmp].nick,tmp_ptr,10);
			bzero(buf,sizeof(buf));
			sprintf(buf,"%s Joined the room\r\n",user[tmp].nick);
			str_len=strlen(buf);
			write_to_socket(j,buf,str_len);
			j=1111; // to end the loop
			break;
		    default:
		      write_to_socket(j,buf,nbytes);
		      break;
		  }
		}
	      }
	    }
	  }
	} 
      }
    }
  }

  return 0;
}


void write_to_socket(int target,char *buff_to_send,int len)
{
  if( !write(target,buff_to_send,len) )
  {
    perror("Write");
    exit(0);
  }
}

int check_for_command(char *buffer,int *p)
{
  char tmp[6];
  strncpy(tmp,buffer,5);
  while(*buffer==' ')
    ++buffer;
  if(!strncmp(buffer,"/SHOW/",6) || !strncmp(buffer,"/show/",6) )
    return SHOW;
  else if(!strncmp(buffer,"/HELP/",6) || !strncmp(buffer,"/help/",6) )
    return HELP;
  else if( strstr(tmp,"/NICK") )
    return NICK;

  else if((*buffer=='/') && (*(buffer+2)=='/'))
  {
    *p= *(buffer+1)-'0';
    return MESSAGE;
  }
  else if( *buffer=='\r')
    return NEWLINE;

  else
    return 0;


}

int is_fd_valid(int destination)
{
  int i;
  for(i=0;i<usercount;++i)
    if( user[i].id==destination)
      return 1;
  return 0;
}

void type_writer(char *buf,int len, int fd)
{
  int i=0;
  for(i=0;i<len;++i)
  {
    write_to_socket(fd,buf+i,sizeof(char));
    usleep(50000);
  }
}