Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Copyright 2014
- *
- * Author: Dinux
- * Description: Simple chatroom in C
- * Version: 1.0
- *
- */
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <arpa/inet.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <pthread.h>
- #include <sys/types.h>
- #define MAX_CLIENTS 100
- static unsigned int cli_count = 0;
- static int uid = 10;
- char **usernames = {"paul","andrei","cipri","truta"};
- char **passwords = {"1","1","1","1"};
- int userCount = 4;
- int checkLogin(char *username,char *passoword){
- int i;
- for(i=0;i<n;i++)
- if(!strcmp(username,usernames[i])&&!strcmp(password,passwords[i]))
- return 1;
- return 0;
- }
- /* Client structure */
- typedef struct {
- struct sockaddr_in addr; /* Client remote address */
- int connfd; /* Connection file descriptor */
- int uid; /* Client unique identifier */
- char name[32]; /* Client name */
- } client_t;
- client_t *clients[MAX_CLIENTS];
- /* Add client to queue */
- void queue_add(client_t *cl){
- int i;
- for(i=0;i<MAX_CLIENTS;i++){
- if(!clients[i]){
- clients[i] = cl;
- return;
- }
- }
- }
- /* Delete client from queue */
- void queue_delete(int uid){
- int i;
- for(i=0;i<MAX_CLIENTS;i++){
- if(clients[i]){
- if(clients[i]->uid == uid){
- clients[i] = NULL;
- return;
- }
- }
- }
- }
- /* Send message to all clients but the sender */
- void send_message(char *s, int uid){
- int i;
- for(i=0;i<MAX_CLIENTS;i++){
- if(clients[i]){
- if(clients[i]->uid != uid){
- write(clients[i]->connfd, s, strlen(s));
- }
- }
- }
- }
- /* Send message to all clients */
- void send_message_all(char *s){
- int i;
- for(i=0;i<MAX_CLIENTS;i++){
- if(clients[i]){
- write(clients[i]->connfd, s, strlen(s));
- }
- }
- }
- /* Send message to sender */
- void send_message_self(const char *s, int connfd){
- write(connfd, s, strlen(s));
- }
- /* Send message to client */
- void send_message_client(char *s, int uid){
- int i;
- for(i=0;i<MAX_CLIENTS;i++){
- if(clients[i]){
- if(clients[i]->uid == uid){
- write(clients[i]->connfd, s, strlen(s));
- }
- }
- }
- }
- /* Send list of active clients */
- void send_active_clients(int connfd){
- int i;
- char s[64];
- for(i=0;i<MAX_CLIENTS;i++){
- if(clients[i]){
- sprintf(s, "<<CLIENT %d | %s\r\n", clients[i]->uid, clients[i]->name);
- send_message_self(s, connfd);
- }
- }
- }
- /* Strip CRLF */
- void strip_newline(char *s){
- while(*s != '\0'){
- if(*s == '\r' || *s == '\n'){
- *s = '\0';
- }
- s++;
- }
- }
- /* Print ip address */
- void print_client_addr(struct sockaddr_in addr){
- printf("%d.%d.%d.%d",
- addr.sin_addr.s_addr & 0xFF,
- (addr.sin_addr.s_addr & 0xFF00)>>8,
- (addr.sin_addr.s_addr & 0xFF0000)>>16,
- (addr.sin_addr.s_addr & 0xFF000000)>>24);
- }
- /* Handle all communication with the client */
- void *handle_client(void *arg){
- char buff_out[1024];
- char buff_in[1024];
- int rlen;
- cli_count++;
- client_t *cli = (client_t *)arg;
- printf("<<ACCEPT ");
- print_client_addr(cli->addr);
- printf(" REFERENCED BY %d\n", cli->uid);
- sprintf(buff_out, "<<JOIN, HELLO %s\r\n", cli->name);
- send_message_all(buff_out);
- /* Receive input from client */
- while((rlen = read(cli->connfd, buff_in, sizeof(buff_in)-1)) > 0){
- buff_in[rlen] = '\0';
- buff_out[0] = '\0';
- strip_newline(buff_in);
- /* Ignore empty buffer */
- if(!strlen(buff_in)){
- continue;
- }
- /* Special options */
- if(buff_in[0] == '\\'){
- char *command, *param, *username, *password;
- command = strtok(buff_in," ");
- if(!strcmp(command, "\\QUIT")){
- break;
- }else if(!strcmp(command, "\\LOGIN")){
- username = strtok(NULL, " ");
- password = strtok(NULL, " ");
- if(username&&password){
- if(checkLogin(username,password)){
- cli->login=1;
- strcpy(cli->name,username);
- sprintf(buff_out, "<<%s loged in \r\n", cli->name);
- send_message_all(buff_out);
- }else{
- send_message_self("<<WRONG USERNAME/PASSWORD\r\n", cli->connfd);
- }
- }else{
- send_message_self("<<WRONG USERNAME/PASSWORD\r\n", cli->connfd);
- }
- }else if(!strcmp(command, "\\PING")){
- send_message_self("<<PONG\r\n", cli->connfd);
- }else if(!strcmp(command, "\\ACTIVE")){
- sprintf(buff_out, "<<CLIENTS %d\r\n", cli_count);
- send_message_self(buff_out, cli->connfd);
- send_active_clients(cli->connfd);
- }else if(!strcmp(command, "\\HELP")){
- strcat(buff_out, "\\QUIT Quit chatroom\r\n");
- strcat(buff_out, "\\PING Server test\r\n");
- strcat(buff_out, "\\NAME <name> Change nickname\r\n");
- strcat(buff_out, "\\PRIVATE <reference> <message> Send private message\r\n");
- strcat(buff_out, "\\ACTIVE Show active clients\r\n");
- strcat(buff_out, "\\HELP Show help\r\n");
- send_message_self(buff_out, cli->connfd);
- }else{
- send_message_self("<<UNKOWN COMMAND\r\n", cli->connfd);
- }
- }else{
- if(cli->login)
- {
- /* Send message */
- sprintf(buff_out, "[%s] %s\r\n", cli->name, buff_in);
- send_message(buff_out, cli->uid);
- }
- else{
- sprintf(buff_out, "PLEASE LOG IN\r\n");
- send_message_self(buff_out, cli->connfd);
- }
- }
- }
- /* Close connection */
- close(cli->connfd);
- sprintf(buff_out, "<<LEAVE, BYE %s\r\n", cli->name);
- send_message_all(buff_out);
- /* Delete client from queue and yeild thread */
- queue_delete(cli->uid);
- printf("<<LEAVE ");
- print_client_addr(cli->addr);
- printf(" REFERENCED BY %d\n", cli->uid);
- free(cli);
- cli_count--;
- pthread_detach(pthread_self());
- return NULL;
- }
- int main(int argc, char *argv[]){
- int listenfd = 0, connfd = 0;
- struct sockaddr_in serv_addr;
- struct sockaddr_in cli_addr;
- pthread_t tid;
- /* Socket settings */
- listenfd = socket(AF_INET, SOCK_STREAM, 0);
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
- serv_addr.sin_port = htons(5000);
- /* Bind */
- if(bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
- perror("Socket binding failed");
- return 1;
- }
- /* Listen */
- if(listen(listenfd, 10) < 0){
- perror("Socket listening failed");
- return 1;
- }
- printf("<[SERVER STARTED]>\n");
- /* Accept clients */
- while(1){
- socklen_t clilen = sizeof(cli_addr);
- connfd = accept(listenfd, (struct sockaddr*)&cli_addr, &clilen);
- /* Check if max clients is reached */
- if((cli_count+1) == MAX_CLIENTS){
- printf("<<MAX CLIENTS REACHED\n");
- printf("<<REJECT ");
- print_client_addr(cli_addr);
- printf("\n");
- close(connfd);
- continue;
- }
- /* Client settings */
- client_t *cli = (client_t *)malloc(sizeof(client_t));
- cli->addr = cli_addr;
- cli->connfd = connfd;
- cli->uid = uid++;
- sprintf(cli->name, "%d", cli->uid);
- /* Add client to the queue and fork thread */
- queue_add(cli);
- pthread_create(&tid, NULL, &handle_client, (void*)cli);
- /* Reduce CPU usage */
- sleep(1);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement