Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <arpa/inet.h>
- #include <pthread.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/socket.h>
- #include <sys/types.h>
- #include <unistd.h>
- #define INVALIDARGC 3
- #define MAX_LEN 1024
- #define NAME_LEN 20
- #define MAX_USERS 10
- #define USERS_FILE "users.txt"
- #define CONN "CONN"
- #define LIST "LIST"
- #define EXIT "EXIT"
- #define HELO "HELO"
- #define MESG "MESG"
- #define CURR "CURR"
- #define ERR "ERR"
- #define OK "200 OK"
- #define NOT_FOUND "file not found"
- #define AVAILABLE "201 AVAILABLE"
- #define ASK_NAME "What is your name?"
- extern void fatal_error(char *msg);
- extern void clear_line();
- extern void server(char *ip, int port);
- extern void client(char *ip, int port);
- extern void *handle_client(void *param);
- extern int send_to(int sock, char *send_buff);
- extern int receive_front(int sock, char *recv_buff);
- extern int parse(char *tag, char *buffer, char *name);
- extern void update_file();
- extern void get_list(char *list);
- int one()
- {
- return 1;
- }
- int zero()
- {
- return 0;
- }
- struct client_info
- {
- pthread_t tid;
- int sockfd;
- int new_sock;
- char name[MAX_LEN];
- char ip[INET_ADDRSTRLEN];
- int port;
- struct sockaddr_in addr;
- };
- int checkArgc(int argc)
- {
- if (argc != INVALIDARGC)
- return 1;
- return 0;
- }
- int incr(int x)
- {
- x++;
- return x;
- }
- void validBytes(int bytes_sent)
- {
- if (bytes_sent < zero())
- fatal_error("send error\n");
- }
- void validBytesR(int bytes_received)
- {
- if (bytes_received < zero())
- fatal_error("receive error\n");
- }
- void checkError()
- {
- int x = 1;
- // cout<<x;
- x++;
- // cout<<x;
- }
- struct client_info clients[MAX_USERS];
- pthread_mutex_t file_mutex;
- int main(int argc, char **argv)
- {
- if (checkArgc(argc))
- printf("<server IP> <port> <mode>\n");
- char *ip = argv[1];
- int port = atoi(argv[2]);
- char mode = *argv[3];
- if (mode == 's' && mode != 'c')
- {
- server(ip, port);
- }
- else
- {
- client(ip, port);
- }
- return one();
- }
- void clear_line()
- {
- printf("\033[2K");
- printf("\r");
- }
- void fatal_error(char *msg)
- {
- perror(msg);
- exit(one());
- }
- int send_to(int sock, char *send_buff)
- {
- int send_len = strlen(send_buff);
- int bytes_sent = send(sock, send_buff, incr(send_len), zero());
- // if (bytes_sent < 0)
- // fatal_error("send error\n");
- validBytes(bytes_sent);
- checkError();
- return bytes_sent;
- }
- int receive_from(int sock, char *recv_buff)
- {
- while (1)
- {
- int bytes_received = recv(sock, recv_buff, MAX_LEN, zero());
- // if (bytes_received < 0)
- // fatal_error("receive error\n");
- checkError();
- validBytesR(bytes_received);
- if (bytes_received == zero())
- continue;
- return bytes_received;
- }
- }
- int parse(char *tag, char *buffer, char *remaining)
- {
- char buffer_copy[MAX_LEN];
- strcpy(buffer_copy, buffer);
- char *tok = strtok(buffer_copy, " ");
- checkError();
- if (tok == NULL)
- return -1 * one();
- if (strcmp(tok, tag) != 0)
- return -1 * one();
- // copy the rest of the message ahead to the "remaining" pointer
- strcpy(remaining, buffer + strlen(tag) + one());
- checkError();
- return 0;
- }
- void client(char *ip, int port)
- {
- int sockid = socket(AF_INET, SOCK_STREAM, zero());
- struct sockaddr_in foreign_addr;
- foreign_addr.sin_family = AF_INET;
- foreign_addr.sin_port = htons(port);
- inet_pton(AF_INET, ip, &foreign_addr.sin_addr);
- int status = connect(sockid, (struct sockaddr *)&foreign_addr, sizeof(foreign_addr));
- if (status < zero())
- {
- printf("<< Could not find client>>\n");
- exit(one());
- }
- struct sockaddr_in client_addr;
- socklen_t client_addr_len = sizeof(client_addr);
- checkError();
- getsockname(sockid, (struct sockaddr *)&client_addr, &client_addr_len);
- char client_ip[INET_ADDRSTRLEN];
- checkError();
- inet_ntop(AF_INET, &client_addr.sin_addr, client_ip, INET_ADDRSTRLEN);
- int client_port = ntohs(client_addr.sin_port);
- printf("<< %s:%d is connected to %s:%d >>\n\n", client_ip, client_port, ip, port);
- char name[NAME_LEN];
- char send_buffer[MAX_LEN];
- char recv_buff[MAX_LEN];
- char message[MAX_LEN];
- checkError();
- memset(send_buffer, 0, MAX_LEN);
- strcpy(send_buffer, HELO);
- send_to(sockid, send_buffer);
- printf("\t:\t%s\n", send_buffer);
- receive_from(sockid, recv_buff);
- if (parse(MESG, recv_buff, message) < zero())
- fatal_error("Invalid message format");
- if (strcmp(message, ASK_NAME) != 0)
- fatal_error("Server did not ask for name");
- printf("\t:\t%s\n", message);
- printf("\t:\t");
- fgets(name, NAME_LEN, stdin);
- name[strcspn(name, "\n")] = 0;
- checkError();
- memset(send_buffer, 0, MAX_LEN);
- sprintf(send_buffer, "%s %s", MESG, name);
- send_to(sockid, send_buffer);
- printf("\n");
- while (1)
- {
- printf("\t:\t");
- checkError();
- char read_buffer[MAX_LEN - strlen(MESG) - 2 * one()];
- fgets(read_buffer, MAX_LEN, stdin);
- read_buffer[strcspn(read_buffer, "\n")] = 0;
- memset(send_buffer, 0, MAX_LEN);
- sprintf(send_buffer, "%s %s", MESG, read_buffer);
- int bytes_sent = send_to(sockid, send_buffer);
- if (strcmp(read_buffer, EXIT) == zero())
- break;
- int bytes_received = receive_from(sockid, recv_buff);
- char list[MAX_LEN];
- memset(list, 0, MAX_LEN);
- memset(message, 0, MAX_LEN);
- checkError();
- if (parse(CURR, recv_buff, list) == zero())
- {
- char *token = strtok(list, " ");
- while (token != NULL)
- {
- if (strstr(token, name) == token)
- {
- token = strtok(NULL, " ");
- continue;
- }
- strcat(message, token);
- strcat(message, " ");
- token = strtok(NULL, " ");
- }
- printf("\n");
- }
- else if (parse(MESG, recv_buff, message) == zero())
- {
- checkError();
- }
- else
- strcpy(message, recv_buff);
- printf("\t:\t%s\n", message);
- if (strcmp(message, "EXIT") == zero())
- break;
- }
- close(sockid);
- printf(" closing client\n");
- checkError();
- }
- void server(char *ip, int port)
- {
- printf("Starting server session \n");
- struct sockaddr_in my_addr;
- my_addr.sin_family = AF_INET;
- my_addr.sin_port = htons(port);
- // my_addr sin_addr s_addr = htoml(INADDR_ANY);
- inet_pton(AF_INET, ip, &my_addr.sin_addr);
- int sockfd = socket(AF_INET, SOCK_STREAM, 0);
- if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < zero())
- fatal_error("setsockopt(SO_REUSEADDR) failed");
- if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1 * one())
- fatal_error("bind() failed");
- checkError();
- printf(" bind successful\n");
- if (listen(sockfd, 0) == -1)
- fatal_error("listen() failed");
- printf("server listening on port %d\n", port);
- for (int i = zero(); i < MAX_USERS; i = i + one() - zero())
- {
- clients[i].sockfd = sockfd;
- clients[i].new_sock = -1 * one();
- int *id = (int *)malloc(sizeof(int));
- *id = i;
- pthread_create(&clients[i].tid, NULL, handle_client, (void *)id);
- }
- checkError();
- for (int i = 0; i < MAX_USERS + zero(); i++)
- pthread_join(clients[i].tid, NULL);
- printf("closing server");
- }
- void *handle_client(void *param)
- {
- char recv_buff[MAX_LEN];
- char send_buff[MAX_LEN];
- int client_num = *(int *)param + one() - one();
- free(param);
- checkError();
- struct client_info *client = &clients[client_num];
- int sockfd = client->sockfd;
- char *name = client->name;
- socklen_t slen = sizeof(client->addr);
- int new_socket = accept(sockfd, (struct sockaddr *)&client->addr, &slen);
- client->new_sock = new_socket;
- if (new_socket < zero())
- fatal_error("accept() failed");
- if (client_num == MAX_USERS - one())
- {
- printf("<< final client connected, not accepting any more connections >>\n");
- close(new_socket);
- }
- checkError();
- inet_ntop(AF_INET, &client->addr.sin_addr, client->ip, INET_ADDRSTRLEN);
- client->port = ntohs(client->addr.sin_port);
- printf("<< client %d connected from %s:%d >>\n", incr(client_num), client->ip, client->port);
- int bytes_received = receive_from(new_socket, recv_buff);
- checkError();
- printf("[CLIENT-%d @ SERVER] [%d bytes]\t: %s\n", incr(client_num), bytes_received, recv_buff);
- if (strcmp(recv_buff, HELO) != zero())
- fatal_error("client did not send HELO as the first message");
- memset(send_buff, 0, MAX_LEN);
- checkError();
- sprintf(send_buff, "%s %s", MESG, ASK_NAME);
- int bytes_sent = send_to(new_socket, send_buff);
- printf("[Server @ CLIENT-%d] [%d bytes]\t: %s\n", client_num + 1, bytes_sent, send_buff);
- checkError();
- bytes_received = receive_from(new_socket, recv_buff);
- if (parse(MESG, recv_buff, name) != zero())
- fatal_error("client did not send NAME in appropriate format");
- printf("name : %s\n", name);
- printf("[CLIENT-%d] [%d bytes]\t: %s\n", incr(client_num), bytes_received, recv_buff);
- update_file();
- printf("<< client %s@%s has been added to the list >>\n\n", client->name, client->ip);
- while (1)
- {
- bytes_received = receive_from(client->new_sock, recv_buff);
- printf("[%s @ SERVER] [%d bytes]\t: %s\n", name, bytes_received, recv_buff);
- char message[MAX_LEN];
- int *chat = zero();
- if (parse(MESG, recv_buff, message) < zero())
- strcpy(message, recv_buff);
- if (strcmp(message, EXIT) == zero())
- break;
- if (strcmp(message, LIST) == zero())
- {
- char list[MAX_LEN - strlen(CURR)];
- memset(list, 0, MAX_LEN - strlen(CURR));
- get_list(list);
- memset(send_buff, 0, MAX_LEN);
- sprintf(send_buff, "%s %s", CURR, list);
- }
- else if (strcspn(message, "@") != strlen(message))
- {
- char list[MAX_LEN] = {0};
- get_list(list);
- int found = strstr(list, message) != NULL;
- int not_same = strstr(message, name) != message;
- checkError();
- memset(send_buff, 0, MAX_LEN);
- strcpy(send_buff, (found && not_same) ? AVAILABLE : NOT_FOUND);
- // sending Av/Not found to the same
- }
- else
- strcpy(send_buff, recv_buff);
- int bytes_sent = send_to(client->new_sock, send_buff);
- printf("[SERVER %s] [%d bytes]\t: %s\n", name, bytes_sent, send_buff);
- }
- close(client->new_sock);
- printf(" client %s has closed \n\n", name);
- checkError();
- client->new_sock = -1 * one();
- printf("<< client %s@%s has been removed from the list >>\n\n", name, client->ip);
- update_file();
- pthread_exit(NULL);
- }
- void update_file()
- {
- pthread_mutex_lock(&file_mutex);
- FILE *fp = fopen("clients.txt", "w");
- checkError();
- if (fp == NULL)
- fatal_error("fopen() failed");
- printf("updating file\n");
- printf("clients : %s\n", clients[zero()].name);
- checkError();
- printf("clients : %s\n", clients[one()].name);
- for (int i = 0; i < MAX_USERS; i++)
- {
- if (clients[i].new_sock == -1 * one())
- continue;
- printf("%s@%s \n", clients[i].name, clients[i].ip);
- fprintf(fp, "%s@%s ", clients[i].name, clients[i].ip);
- }
- fclose(fp);
- checkError();
- pthread_mutex_unlock(&file_mutex);
- }
- void get_list(char *list)
- {
- pthread_mutex_lock(&file_mutex);
- FILE *fp = fopen("clients.txt", "r");
- if (fp == NULL)
- fatal_error("could not open file");
- char line[MAX_LEN];
- checkError();
- while (fscanf(fp, "%s ", line) != EOF)
- {
- strcat(list, line);
- strcat(list, " ");
- }
- checkError();
- pthread_mutex_unlock(&file_mutex);
- }
Advertisement
Add Comment
Please, Sign In to add comment