/***************************************************************************** * Example: Chat server using NetLib - gets uid of connections if possible * Author: Simon Amor * Sets up a simple chat server on specified port of your machine ***/ #include #include #include #include #include /* #includes Netlib requires */ #include #include #include #include #include #include #include #include #include /* Netlib include */ #include extern fdopen(int, char *); extern strcasecmp(const char *, const char *); #define BUFLEN 1024 #define CONNS 20 #define PORT 7777 #define COMCHAR '.' /* Define a simple macro for socket checking */ #define CheckActive(x,f) FD_ISSET(x,f) /* array of file descriptors - 0=not used */ int fd_array[CONNS]; /* store the logins */ char login[CONNS][40]; char *global_string; /* flag for whether the server is shutting down or not, YES=1 */ int server_down; /* Converts chars to upper case, toupper() macros sometimes fails */ int Toupper(c) int c; { if (islower(c)) return toupper(c); else return c; } /* Filter <32 and >126, but not 13 or 10 from string */ char *filter(char *string) { char *temp=malloc(strlen(string)+3); int loop,pos; if (temp==NULL) return NULL; pos=0; for (loop=0;loop31) && (string[loop]<127)) temp[pos++]=string[loop]; } temp[pos++]='\n'; temp[pos++]='\r'; temp[pos++]='\0'; return temp; } /***************************************************************************** * Transmit a string to a list of connections ***/ int broadcast(int max_connects,int *fd_list,char *send_buffer) { int broadloop; /* Print send buffer to stdout & flush (for redirecting to a file) */ printf("%s",send_buffer); fflush(stdout); for (broadloop=0;broadloop0) NetPutString(fd_list[broadloop],send_buffer); } return 0; } /***************************************************************************** * Handle SIGINT & SIGTERM ***/ void signal_handler() { broadcast(CONNS,(int *)&fd_array,">>> Shutting down <<<\n"); server_down=1; } /***************************************************************************** * process a command ***/ int process_command(char *buffer,int counter) { while ((buffer[strlen(buffer)-1]=='\n') || (buffer[strlen(buffer)-1]=='\r')) { buffer[strlen(buffer)-1]='\0'; } if (!strcasecmp(buffer,"quit")) { NetClose(fd_array[counter]); sprintf(global_string,"Connection closed to line %d\n",counter+1); fd_array[counter]=0; broadcast(CONNS,(int *)&fd_array,global_string); return 1; } return 0; } /***************************************************************************** * Main loop ***/ int main() { struct sockaddr_in server; fd_set readfds; char *buffer=malloc(BUFLEN); char *temp; char *send_buffer=malloc(BUFLEN+10); int mastersocket; int newsocket, ok=0; int new_conns; int max_conns=sysconf(_SC_OPEN_MAX); int counter; char *uid; global_string=malloc(1024); /* check buffers were allocated ok */ if ((buffer==NULL) || (send_buffer==NULL) || (global_string==NULL)) { perror("Buffer allocation error"); exit(EXIT_FAILURE); } server_down=0; printf("To stop this server, type CTRL-C\n"); /* initialise the fd_array to zeros */ for (counter=0;counter0 then add it to the list to be checked */ for (counter=0;counter0) { printf("New socket open as file descriptor %d\n",newsocket); NetPutString(newsocket,"Welcome to the NetLib example server\n"); /* check if server reached maximum connections */ counter=0; while ((counterh_name, 20); } else { strncpy(login[counter], gethostbyaddr((char *)&server.sin_addr, sizeof(struct in_addr), AF_INET)->h_name, 29); } } } } else /* activity must be on user connection */ { /* check for any input from each user connection */ for (counter=0; counter2) { sprintf(send_buffer,"%-30s| %s", login[counter], temp); broadcast(CONNS,(int *)&fd_array,send_buffer); } /* strlen > 0 */ free(temp); } /* malloc */ } /* speech */ } /* NetGetString ok */ } /* CheckActive */ } /* counter */ } /* connection activity */ } /* while loop */ return(0); } /* main */