set a nickname, a username, join a channel,
send and receive private messages using your reference client and All the messages sent from one client to a channel have to be forwarded to every other client that joined the channel and still need to add operators and regular users and please don't touch my code hahahaha
This commit is contained in:
54
.vscode/settings.json
vendored
Normal file
54
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"files.associations": {
|
||||
"ostream": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"csignal": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"map": "cpp",
|
||||
"sstream": "cpp"
|
||||
}
|
||||
}
|
216
Server.cpp
216
Server.cpp
@@ -113,6 +113,157 @@ void Server::handleClientConnection() {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// FUNCTIONS OF TOP GGGGGG.. START FROM HEEEREEE
|
||||
|
||||
|
||||
|
||||
|
||||
std::string trim(const std::string& str) {
|
||||
// Find the first non-whitespace character
|
||||
size_t first = str.find_first_not_of(" \t\n\r");
|
||||
|
||||
// If the string is all whitespace, return an empty string
|
||||
if (std::string::npos == first) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Find the last non-whitespace character
|
||||
size_t last = str.find_last_not_of(" \t\n\r");
|
||||
|
||||
// Return the trimmed substring
|
||||
return str.substr(first, last - first + 1);
|
||||
}
|
||||
|
||||
void Server::createChannel(const std::string& channelName, const std::string& nickname) {
|
||||
// Check if the channel already exists
|
||||
if (channels.find(channelName) == channels.end()) {
|
||||
// Channel doesn't exist, so create it
|
||||
std::vector<std::string> users;
|
||||
users.push_back(nickname); // Add the user to the channel
|
||||
channels[channelName] = users;
|
||||
std::cout << "Channel '" << channelName << "' created by '" << nickname << "'" << std::endl;
|
||||
} else {
|
||||
// Channel already exists, just add the user to it
|
||||
channels[channelName].push_back(nickname);
|
||||
std::cout << "User '" << nickname << "' joined channel '" << channelName << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool startsWith(const std::string& str, const std::string& prefix) {
|
||||
return str.substr(0, prefix.length()) == prefix;
|
||||
}
|
||||
|
||||
void Server::setNickname(int fd, const std::string& nickname) {
|
||||
nicknames[fd] = nickname; // Associate the nickname with the client's socket descriptor
|
||||
}
|
||||
|
||||
void Server::setUsername(int fd, const std::string& username) {
|
||||
usernames[fd] = username; // Associate the nickname with the client's socket descriptor
|
||||
}
|
||||
|
||||
void sendResponse(int fd, const std::string& message) {
|
||||
// Convert the message string to a C-style string
|
||||
const char* msg = message.c_str();
|
||||
|
||||
// Get the length of the message
|
||||
size_t len = strlen(msg);
|
||||
|
||||
// Send the message to the client
|
||||
ssize_t bytesSent = send(fd, msg, len, 0);
|
||||
|
||||
// Check if the send operation was successful
|
||||
if (bytesSent == -1) {
|
||||
// Handle send error
|
||||
// You can log an error message or take appropriate action
|
||||
std::cerr << "Error sending response to client <" << fd << ">" << std::endl;
|
||||
} else {
|
||||
// Output the sent message to the console
|
||||
std::cout << "Response sent to client <" << fd << ">: " << message << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int findUserFd(const std::string& nickname, const std::map<int, std::string>& usernames) {
|
||||
// Iterate over each entry in the usernames map
|
||||
for (std::map<int, std::string>::const_iterator it = usernames.begin(); it != usernames.end(); ++it) {
|
||||
// Check if the nickname matches
|
||||
if (it->second == nickname) {
|
||||
// Return the file descriptor associated with the nickname
|
||||
return it->first;
|
||||
}
|
||||
}
|
||||
// Return -1 if the nickname is not found
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Server::handlePrivateMessage(int senderFd, const std::string& recipient, const std::string& message) {
|
||||
// Find the recipient's connection (socket file descriptor)
|
||||
int recipientFd = findUserFd(recipient, usernames);
|
||||
|
||||
if (recipientFd != -1) {
|
||||
// Forward the private message to the recipient's client
|
||||
std::string privateMessage = "PRIVATE " + usernames[senderFd] + ": " + message + "\n";
|
||||
send(recipientFd, privateMessage.c_str(), privateMessage.length(), 0);
|
||||
} else {
|
||||
// Handle case where recipient is not found (e.g., user not online)
|
||||
std::string errorMessage = "Error: User '" + recipient + "' not found or offline\n";
|
||||
send(senderFd, errorMessage.c_str(), errorMessage.length(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
int Server::findUserFd1(const std::string& nickname) {
|
||||
std::map<int, std::string>::iterator it;
|
||||
for (it = nicknames.begin(); it != nicknames.end(); ++it) {
|
||||
if (it->second == nickname) {
|
||||
return it->first; // Return the file descriptor if the nickname matches
|
||||
}
|
||||
}
|
||||
return -1; // Return -1 if the nickname is not found
|
||||
}
|
||||
|
||||
void Server::broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg) {
|
||||
// Check if the channel exists
|
||||
if (channels.find(channel) == channels.end()) {
|
||||
std::cerr << "Channel " << channel << " does not exist" << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
// Iterate through all clients in the channel and send the message
|
||||
// Get a reference to the vector of clients in the channel
|
||||
const std::vector<std::string>& clients = channels[channel];
|
||||
|
||||
// Iterate over the vector using iterators
|
||||
std::vector<std::string>::const_iterator it;
|
||||
for (it = clients.begin(); it != clients.end(); ++it) {
|
||||
// Get the current client nickname
|
||||
const std::string& client = *it;
|
||||
|
||||
// Find the file descriptor associated with the client nickname
|
||||
int recipientFd = findUserFd1(client);
|
||||
|
||||
// If the file descriptor is found, send the message to the client
|
||||
if (recipientFd != -1) {
|
||||
std::string message = "PRIVMSG " + channel + " :" + senderNickname + ": " + msg + "\r\n";
|
||||
send(recipientFd, message.c_str(), message.size(), 0);
|
||||
} else {
|
||||
// If the file descriptor is not found, print an error message
|
||||
std::cerr << "Client " << client << " not found" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// ........AND FINISH HERE ......//////
|
||||
|
||||
|
||||
void Server::handleClientData(int fd) {
|
||||
std::string command;
|
||||
char buffer[BUFFER_SIZE];
|
||||
@@ -134,7 +285,69 @@ void Server::handleClientData(int fd) {
|
||||
} else {
|
||||
command.append(buffer, bytesRead - 1);
|
||||
std::cout << "Received data from client " << fd << ": " << command << std::endl;
|
||||
// process the command here
|
||||
|
||||
//******************* FROM THERE IM STARTING TOP GGG ************ .
|
||||
if (startsWith(command, "/setnick ")) {
|
||||
// Extract the nickname from the command
|
||||
std::string nickname = command.substr(9); // Assuming "/setnick " is 9 characters long
|
||||
|
||||
// Handle setting the nickname for the client's connection
|
||||
setNickname(fd, nickname);
|
||||
|
||||
// Send a response back to the client confirming the action
|
||||
sendResponse(fd, "Nickname set to: " + nickname);
|
||||
} else if (startsWith(command, "/setuser ")) {
|
||||
std::string username = command.substr(9);
|
||||
|
||||
setUsername(fd, username);
|
||||
|
||||
sendResponse(fd, "Username set to: " + username);
|
||||
|
||||
// Process other commands or messages
|
||||
// processCommand(fd, command);
|
||||
} else if (startsWith(command, "/join ")) {
|
||||
std::string chanelname = command.substr(5);
|
||||
chanelname = trim(chanelname);
|
||||
createChannel(chanelname, nicknames[fd]);
|
||||
|
||||
} else if (startsWith(command, "PRIVMSG ")) {
|
||||
// Extract the recipient and the message from the command
|
||||
std::istringstream iss(command);
|
||||
std::string cmd, recipient, message;
|
||||
iss >> cmd >> recipient;
|
||||
recipient = trim(recipient);
|
||||
std::getline(iss, message);
|
||||
message = trim(message);
|
||||
if (recipient[0] == '#')
|
||||
{
|
||||
recipient = recipient.substr(1);
|
||||
std::cout << "this the chanel name and was good : " << recipient << std::endl;
|
||||
broadcastMessage(recipient, nicknames[fd], message);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (message[0] == ':') {
|
||||
message = message.substr(1);
|
||||
handlePrivateMessage(fd, recipient, message);
|
||||
}
|
||||
|
||||
}
|
||||
// Remove the colon from the recipient if present
|
||||
// if (!recipient.empty() && recipient[1] == ':') {
|
||||
// recipient = recipient.substr(1);
|
||||
// }
|
||||
|
||||
|
||||
// Read the rest of the line as the message
|
||||
|
||||
// if (message[0] == ':')
|
||||
// message = message.substr(1);
|
||||
|
||||
// Print the extracted recipient and message for debugging
|
||||
std::cout << "Recipient: " << recipient << std::endl;
|
||||
std::cout << "Message: " << message << std::endl;
|
||||
}
|
||||
//**************** STOOOOOOP HERE TOP G ...
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -148,6 +361,7 @@ void Server::handleClientData(int fd) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Server::clientCleanup(int fd) {
|
||||
for (std::vector<pollfd>::iterator it = _fds.begin(); it != _fds.end(); ++it) {
|
||||
if (it->fd == fd) {
|
||||
|
23
Server.hpp
23
Server.hpp
@@ -1,6 +1,11 @@
|
||||
#ifndef SERVER_HPP
|
||||
#define SERVER_HPP
|
||||
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <unistd.h> // Include for the send function
|
||||
#include <cstring> // Include for the strlen function
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <csignal>
|
||||
@@ -10,8 +15,10 @@
|
||||
#include <poll.h>
|
||||
#include "Client.hpp"
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#define BUFFER_SIZE 1024
|
||||
|
||||
|
||||
class Server {
|
||||
private:
|
||||
int _port;
|
||||
@@ -20,10 +27,24 @@ class Server {
|
||||
std::string _password;
|
||||
std::vector<struct pollfd> _fds;
|
||||
std::vector<Client> _clients;
|
||||
// THAT'S THA DATA OF TOOOP GGG START FROM THERE .
|
||||
std::map<int, std::string> nicknames; // Replace unordered_map with map
|
||||
std::map<int, std::string> usernames; // Replace unordered_map with map
|
||||
std::map<std::string, std::vector<std::string> > channels; //here a chanel name and list of client in every chanel
|
||||
|
||||
|
||||
|
||||
public:
|
||||
Server();
|
||||
~Server();
|
||||
|
||||
// THAT'S MY FUNCTIONS START FROM THERE
|
||||
void setNickname(int fd, const std::string& nickname);
|
||||
void setUsername(int fd, const std::string& username);
|
||||
void createChannel(const std::string& channel, const std::string& nickname);
|
||||
void handlePrivateMessage(int senderFd, const std::string& recipient, const std::string& message);
|
||||
void broadcastMessage(const std::string& channel, const std::string& senderNickname, const std::string& msg);
|
||||
int findUserFd1(const std::string& nickname);
|
||||
// AND END HERE.
|
||||
void parseArgs(int ac, char **av);
|
||||
static void receiveSignal(int signum);
|
||||
void init();
|
||||
|
Reference in New Issue
Block a user