Skip to content

Commit 4fe0d43

Browse files
feat: whisper
1 parent 563f632 commit 4fe0d43

2 files changed

Lines changed: 76 additions & 9 deletions

File tree

chatServer.cpp

Lines changed: 68 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,20 @@ struct client{
2525
// Keep track of FDs of all connected clients
2626
std::vector<int> sock_fds;
2727

28+
// Keep track of all users and their sock_fds
29+
std::unordered_map<int, int> users;
30+
31+
// Available commands
32+
const char *commands = {"whisper"};
33+
2834
// Mutex for sync
2935
pthread_mutex_t sock_fds_mutex PTHREAD_MUTEX_INITIALIZER;
36+
pthread_mutex_t users_mutex PTHREAD_MUTEX_INITIALIZER;
3037

3138
// Broadcasts received messages to all clients
32-
void broadcastMsg(const char *data, const char *username){
39+
void broadcastMsg(const char *data, const char *username, int uid){
3340
char message[BUFLEN];
34-
snprintf(message, sizeof(message), "%s : %s", username, data);
41+
snprintf(message, sizeof(message), "%s [%d]: %s", username, uid, data);
3542

3643
pthread_mutex_lock(&sock_fds_mutex);
3744
for(auto sock_fd : sock_fds){
@@ -40,6 +47,23 @@ void broadcastMsg(const char *data, const char *username){
4047
pthread_mutex_unlock(&sock_fds_mutex);
4148
}
4249

50+
// Whisper private message to a client
51+
int whisperMsg(int uid, const char *username, const char *private_msg){
52+
int sock_fd;
53+
char message[BUFLEN];
54+
snprintf(message, sizeof(message), "[WHISPER] %s [%d]: %s", username, uid, private_msg);
55+
56+
pthread_mutex_lock(&users_mutex);
57+
sock_fd = users[uid];
58+
pthread_mutex_unlock(&users_mutex);
59+
60+
if(write(sock_fd, message, sizeof(message))==-1){
61+
std::cout << "Failed to whisper message to client!" << std::endl;
62+
return 0;
63+
}
64+
return 1;
65+
}
66+
4367
// Read data from clients
4468
void *handleClient(void *client){
4569
char username[20];
@@ -49,12 +73,14 @@ void *handleClient(void *client){
4973
int uid = c->uid;
5074
strcpy(username, c->username);
5175
username[strcspn(username, "\n")] = '\0';
52-
5376
std::cout << username << " joined!\n" << std::endl;
77+
5478
pthread_mutex_lock(&sock_fds_mutex);
5579
sock_fds.push_back(sock_fd);
5680
pthread_mutex_unlock(&sock_fds_mutex);
81+
5782
char r_buff[BUFLEN];
83+
char private_msg[BUFLEN];
5884

5985
while(1){
6086
// Recieve data from a single client
@@ -64,16 +90,49 @@ void *handleClient(void *client){
6490
std::cout << username << " disconnected!" << std::endl;
6591
break;
6692
}
67-
68-
std::cout << username << " says: " << r_buff << std::endl;
6993

70-
// Broadcast data to all clients
71-
broadcastMsg(r_buff, username);
94+
// Command is received
95+
if(r_buff[0]=='/'){
96+
char command[10];
97+
char user_id[10];
98+
bzero(private_msg, sizeof(private_msg));
99+
100+
char *ptr = r_buff + 1;
101+
char *temp;
102+
temp = strtok(ptr, " ");
103+
int args = 0;
104+
while(temp!=NULL){
105+
if(args==0){
106+
strcpy(command, temp);
107+
args++;
108+
}else if(args==1){
109+
strcpy(user_id, temp);
110+
args++;
111+
}else{
112+
strcat(private_msg, temp);
113+
strcat(private_msg, " ");
114+
}
115+
temp = strtok(NULL, " ");
116+
}
117+
118+
whisperMsg(atoi(user_id), username, private_msg);
119+
}else{
120+
// Message is received
121+
std::cout << username << "[" << uid << "]" << " says: " << r_buff << std::endl;
122+
123+
// Broadcast data to all clients
124+
broadcastMsg(r_buff, username, uid);
125+
}
72126
}
73127

74128
pthread_mutex_lock(&sock_fds_mutex);
75129
sock_fds.erase(std::remove(sock_fds.begin(), sock_fds.end(), sock_fd), sock_fds.end());
76130
pthread_mutex_unlock(&sock_fds_mutex);
131+
132+
pthread_mutex_lock(&users_mutex);
133+
users.erase(uid);
134+
pthread_mutex_unlock(&users_mutex);
135+
77136
close(sock_fd);
78137
free(c);
79138
return NULL;
@@ -137,6 +196,8 @@ int main(int argc, char **argv){
137196
c->client_sock_fd = client_fd;
138197
c->uid = uid;
139198
strcpy(c->username, username);
199+
200+
users[uid] = client_fd;
140201

141202
// Create a new thread for every client
142203
pthread_t tid;

client.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include <iostream>
22
#include <unistd.h>
3+
#include <iomanip>
34
#include <bits/stdc++.h>
45

56
#include <arpa/inet.h>
@@ -34,9 +35,14 @@ void chat(int sock_fd){
3435
char s_buff[BUFLEN];
3536

3637
while(1){
37-
// Send message to server
38+
// Send data to server
3839
bzero(s_buff, sizeof(s_buff));
39-
std::cout << "Enter message to send to server: ";
40+
std::cout << "Enter a message or command to send: ";
41+
std::cout << "\n*****\n";
42+
std::cout << "Available commands: \n" << std::setw(20) << std::endl;
43+
std::cout << "/whisper - " << "Send data to a particular client based on their ID - [Example usage: /whisper 29 Hello James]" << std::setw(10);
44+
std::cout << "\n*****\n";
45+
4046
fgets(s_buff, sizeof(s_buff), stdin);
4147
write(sock_fd, s_buff, strlen(s_buff));
4248
}

0 commit comments

Comments
 (0)