push
This commit is contained in:
parent
f1a7e3e8f7
commit
6732e59a03
|
|
@ -0,0 +1,25 @@
|
||||||
|
irssi
|
||||||
|
/connect localhost 6667 pass
|
||||||
|
/nick bob
|
||||||
|
/quote NICK 1abc
|
||||||
|
/quote PING coucou
|
||||||
|
/join #test
|
||||||
|
/quote PRIVMSG #test :salut
|
||||||
|
/quote PRIVMSG bob :coucou
|
||||||
|
/part #test
|
||||||
|
/join #test
|
||||||
|
/quote TOPIC #test
|
||||||
|
/quote TOPIC #test :nouveau sujet
|
||||||
|
/quote MODE #test +i
|
||||||
|
/quote MODE #test -i
|
||||||
|
/quote MODE #test +t
|
||||||
|
/quote MODE #test -t
|
||||||
|
/quote MODE #test +k secret
|
||||||
|
/quote MODE #test -k
|
||||||
|
/quote MODE #test +l 2
|
||||||
|
/quote MODE #test -l
|
||||||
|
/quote MODE #test +o alice
|
||||||
|
/quote MODE #test -o alice
|
||||||
|
/quote INVITE alice #test
|
||||||
|
/quote KICK #test alice
|
||||||
|
/quote QUIT
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
# include <iostream>
|
# include <iostream>
|
||||||
# include <stdexcept>
|
# include <stdexcept>
|
||||||
# include <cstring>
|
# include <cstring>
|
||||||
|
# include <csignal>
|
||||||
# include <cerrno>
|
# include <cerrno>
|
||||||
# include "CommandValidator.hpp"
|
# include "CommandValidator.hpp"
|
||||||
# include "Channel.hpp"
|
# include "Channel.hpp"
|
||||||
|
|
|
||||||
10
main.cpp
10
main.cpp
|
|
@ -1,7 +1,15 @@
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <csignal>
|
||||||
#include "Server.hpp"
|
#include "Server.hpp"
|
||||||
|
|
||||||
|
volatile sig_atomic_t g_stop = 0;
|
||||||
|
|
||||||
|
void handleSig(int)
|
||||||
|
{
|
||||||
|
g_stop = 1;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
if (argc != 3)
|
if (argc != 3)
|
||||||
|
|
@ -15,6 +23,8 @@ int main(int argc, char **argv)
|
||||||
std::cerr << "Error: invalid port" << std::endl;
|
std::cerr << "Error: invalid port" << std::endl;
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
|
signal(SIGINT, handleSig);
|
||||||
|
signal(SIGQUIT, handleSig);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Server server(port, argv[2]);
|
Server server(port, argv[2]);
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,10 @@ bool IrcMessage::hasParam(size_t index) const
|
||||||
|
|
||||||
const std::string &IrcMessage::param(size_t index) const
|
const std::string &IrcMessage::param(size_t index) const
|
||||||
{
|
{
|
||||||
return (_params[index]);
|
static const std::string empty;
|
||||||
|
if (index >= _params.size())
|
||||||
|
return (empty);
|
||||||
|
return (_params[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t IrcMessage::paramCount(void) const
|
size_t IrcMessage::paramCount(void) const
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#include "Server.hpp"
|
#include "Server.hpp"
|
||||||
|
|
||||||
|
extern volatile sig_atomic_t g_stop;
|
||||||
|
|
||||||
void Server::start(void)
|
void Server::start(void)
|
||||||
{
|
{
|
||||||
_serverFd = socket(AF_INET, SOCK_STREAM, 0);
|
_serverFd = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
|
|
@ -36,7 +38,7 @@ void Server::start(void)
|
||||||
pollfd.events = POLLIN;
|
pollfd.events = POLLIN;
|
||||||
pollfd.revents = 0;
|
pollfd.revents = 0;
|
||||||
_fds.push_back(pollfd);
|
_fds.push_back(pollfd);
|
||||||
std::cout << "FT_IRC server startded on " << _port << " Port." << std::endl << "The password is \"" << _password << "\"." << std::endl;
|
std::cout << "FT_IRC server startded on " << _port << " Port." << std::endl << "The password is \"" << _password << "\"." << std::endl << "Ctrl+c for shutdown the server" << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConnectedUser::ConnectedUser(void) : fd(-1), passOk(false), nickOk(false), userOk(false)
|
ConnectedUser::ConnectedUser(void) : fd(-1), passOk(false), nickOk(false), userOk(false)
|
||||||
|
|
@ -87,11 +89,29 @@ Server::~Server(void)
|
||||||
|
|
||||||
void Server::sendReply(int fd, const std::string &msg)
|
void Server::sendReply(int fd, const std::string &msg)
|
||||||
{
|
{
|
||||||
send(fd, msg.c_str(), msg.size(), 0);
|
size_t total = 0;
|
||||||
|
while (total < msg.size())
|
||||||
|
{
|
||||||
|
ssize_t s = send(fd, msg.c_str() + total, msg.size() - total, 0);
|
||||||
|
if (s <= 0)
|
||||||
|
return ;
|
||||||
|
total += static_cast<size_t>(s);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::removeUser(int fd)
|
void Server::removeUser(int fd)
|
||||||
{
|
{
|
||||||
|
std::map<std::string, Channel>::iterator it = _channels.begin();
|
||||||
|
while (it != _channels.end())
|
||||||
|
{
|
||||||
|
it->second.removeMember(fd);
|
||||||
|
it->second.removeOperator(fd);
|
||||||
|
it->second.removeInvited(fd);
|
||||||
|
if (it->second.memberCount() == 0)
|
||||||
|
_channels.erase(it++);
|
||||||
|
else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
_users.erase(fd);
|
_users.erase(fd);
|
||||||
for (size_t i = 0; i < _fds.size(); i++)
|
for (size_t i = 0; i < _fds.size(); i++)
|
||||||
|
|
@ -108,7 +128,7 @@ void Server::acceptNew(void)
|
||||||
{
|
{
|
||||||
int newFd = accept(_serverFd, NULL, NULL);
|
int newFd = accept(_serverFd, NULL, NULL);
|
||||||
if (newFd == -1)
|
if (newFd == -1)
|
||||||
throw std::runtime_error(strerror(errno));
|
return ;
|
||||||
fcntl(newFd, F_SETFL, O_NONBLOCK);
|
fcntl(newFd, F_SETFL, O_NONBLOCK);
|
||||||
int flag = 1;
|
int flag = 1;
|
||||||
setsockopt(newFd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
setsockopt(newFd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||||
|
|
@ -143,12 +163,16 @@ void Server::handleRecv(int fd)
|
||||||
_users[fd].parseBuffer.append(buf, n);
|
_users[fd].parseBuffer.append(buf, n);
|
||||||
std::vector<IrcMessage> messages = _users[fd].parseBuffer.extractMessages();
|
std::vector<IrcMessage> messages = _users[fd].parseBuffer.extractMessages();
|
||||||
for (size_t i = 0; i < messages.size(); i++)
|
for (size_t i = 0; i < messages.size(); i++)
|
||||||
|
{
|
||||||
|
if (_users.find(fd) == _users.end())
|
||||||
|
break ;
|
||||||
dispatch(fd, messages[i]);
|
dispatch(fd, messages[i]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::run(void)
|
void Server::run(void)
|
||||||
{
|
{
|
||||||
while (true)
|
while (!g_stop)
|
||||||
{
|
{
|
||||||
int ret = poll(_fds.data(), _fds.size(), -1);
|
int ret = poll(_fds.data(), _fds.size(), -1);
|
||||||
if (ret == -1)
|
if (ret == -1)
|
||||||
|
|
@ -163,8 +187,14 @@ void Server::run(void)
|
||||||
removeUser(fd);
|
removeUser(fd);
|
||||||
i--;
|
i--;
|
||||||
}
|
}
|
||||||
else if ( _fds[i].revents & POLLIN)
|
else if (_fds[i].revents & POLLIN)
|
||||||
|
{
|
||||||
|
size_t before = _fds.size();
|
||||||
handleRecv(_fds[i].fd);
|
handleRecv(_fds[i].fd);
|
||||||
|
if (_fds.size() < before)
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -221,9 +251,38 @@ void Server::handlePass(int fd, const IrcMessage &msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isNickChar(char c, bool first)
|
||||||
|
{
|
||||||
|
if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
|
||||||
|
return (true);
|
||||||
|
if (c == '[' || c == ']' || c == '\\' || c == '`'
|
||||||
|
|| c == '_' || c == '^' || c == '{' || c == '|' || c == '}')
|
||||||
|
return (true);
|
||||||
|
if (!first && ((c >= '0' && c <= '9') || c == '-'))
|
||||||
|
return (true);
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isValidNick(const std::string &nick)
|
||||||
|
{
|
||||||
|
if (nick.empty())
|
||||||
|
return (false);
|
||||||
|
for (size_t i = 0; i < nick.size(); ++i)
|
||||||
|
{
|
||||||
|
if (!isNickChar(nick[i], i == 0))
|
||||||
|
return (false);
|
||||||
|
}
|
||||||
|
return (true);
|
||||||
|
}
|
||||||
|
|
||||||
void Server::handleNick(int fd, const IrcMessage &msg)
|
void Server::handleNick(int fd, const IrcMessage &msg)
|
||||||
{
|
{
|
||||||
std::string newNick = msg.param(0);
|
std::string newNick = msg.param(0);
|
||||||
|
if (!isValidNick(newNick))
|
||||||
|
{
|
||||||
|
sendReply(fd, "432 * " + newNick + " :Erroneous nickname\r\n");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
std::map<int, ConnectedUser>::iterator it = _users.begin();
|
std::map<int, ConnectedUser>::iterator it = _users.begin();
|
||||||
for (; it != _users.end(); it++)
|
for (; it != _users.end(); it++)
|
||||||
{
|
{
|
||||||
|
|
@ -233,8 +292,28 @@ void Server::handleNick(int fd, const IrcMessage &msg)
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
bool wasRegistered = _users[fd].isRegistered();
|
||||||
|
std::string oldNick = _users[fd].nick;
|
||||||
_users[fd].nick = newNick;
|
_users[fd].nick = newNick;
|
||||||
_users[fd].nickOk = true;
|
_users[fd].nickOk = true;
|
||||||
|
if (wasRegistered && oldNick != newNick)
|
||||||
|
{
|
||||||
|
std::string notice = ":" + oldNick + "!" + _users[fd].username
|
||||||
|
+ "@localhost NICK " + newNick + "\r\n";
|
||||||
|
std::map<int, bool> seen;
|
||||||
|
seen[fd] = true;
|
||||||
|
for (std::map<std::string, Channel>::iterator cit = _channels.begin();
|
||||||
|
cit != _channels.end(); ++cit)
|
||||||
|
{
|
||||||
|
if (!cit->second.hasMember(fd))
|
||||||
|
continue ;
|
||||||
|
const std::vector<int> &mem = cit->second.getMembers();
|
||||||
|
for (size_t i = 0; i < mem.size(); ++i)
|
||||||
|
seen[mem[i]] = true;
|
||||||
|
}
|
||||||
|
for (std::map<int, bool>::iterator sit = seen.begin(); sit != seen.end(); ++sit)
|
||||||
|
sendReply(sit->first, notice);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handleUser(int fd, const IrcMessage &msg)
|
void Server::handleUser(int fd, const IrcMessage &msg)
|
||||||
|
|
@ -327,6 +406,8 @@ void Server::handlePart(int fd, const IrcMessage &msg)
|
||||||
std::string msg_rm = ":" + _users[fd].nick + "!" + _users[fd].username + "@localhost PART " + chanName + "\r\n";
|
std::string msg_rm = ":" + _users[fd].nick + "!" + _users[fd].username + "@localhost PART " + chanName + "\r\n";
|
||||||
broadcastToChannel(chanName, msg_rm, -1);
|
broadcastToChannel(chanName, msg_rm, -1);
|
||||||
chan.removeMember(fd);
|
chan.removeMember(fd);
|
||||||
|
chan.removeOperator(fd);
|
||||||
|
chan.removeInvited(fd);
|
||||||
if (chan.memberCount() == 0)
|
if (chan.memberCount() == 0)
|
||||||
_channels.erase(chanName);
|
_channels.erase(chanName);
|
||||||
}
|
}
|
||||||
|
|
@ -408,6 +489,8 @@ void Server::handleKick(int fd, const IrcMessage &msg)
|
||||||
std::string kick_msg = ":" + _users[fd].nick + "!" + _users[fd].username + "@localhost KICK " + chanName + " " + targetNick + "\r\n";
|
std::string kick_msg = ":" + _users[fd].nick + "!" + _users[fd].username + "@localhost KICK " + chanName + " " + targetNick + "\r\n";
|
||||||
broadcastToChannel(chanName, kick_msg, -1);
|
broadcastToChannel(chanName, kick_msg, -1);
|
||||||
chan.removeMember(targetFd);
|
chan.removeMember(targetFd);
|
||||||
|
chan.removeOperator(targetFd);
|
||||||
|
chan.removeInvited(targetFd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::handleInvite(int fd, const IrcMessage &msg)
|
void Server::handleInvite(int fd, const IrcMessage &msg)
|
||||||
|
|
@ -486,6 +569,8 @@ void Server::handleMode(int fd, const IrcMessage &msg)
|
||||||
{
|
{
|
||||||
std::string chanName = msg.param(0);
|
std::string chanName = msg.param(0);
|
||||||
std::string modeStr = msg.param(1);
|
std::string modeStr = msg.param(1);
|
||||||
|
if (modeStr.size() < 2 || (modeStr[0] != '+' && modeStr[0] != '-'))
|
||||||
|
return ;
|
||||||
if (chanName.empty() || chanName[0] != '#')
|
if (chanName.empty() || chanName[0] != '#')
|
||||||
return ;
|
return ;
|
||||||
if (_channels.find(chanName) == _channels.end())
|
if (_channels.find(chanName) == _channels.end())
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue