@@ -25,13 +25,20 @@ struct client{
2525// Keep track of FDs of all connected clients
2626std::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
2935pthread_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
4468void *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;
0 commit comments