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 <stdexcept>
|
||||
# include <cstring>
|
||||
# include <csignal>
|
||||
# include <cerrno>
|
||||
# include "CommandValidator.hpp"
|
||||
# include "Channel.hpp"
|
||||
|
|
|
|||
10
main.cpp
10
main.cpp
|
|
@ -1,7 +1,15 @@
|
|||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <csignal>
|
||||
#include "Server.hpp"
|
||||
|
||||
volatile sig_atomic_t g_stop = 0;
|
||||
|
||||
void handleSig(int)
|
||||
{
|
||||
g_stop = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (argc != 3)
|
||||
|
|
@ -15,6 +23,8 @@ int main(int argc, char **argv)
|
|||
std::cerr << "Error: invalid port" << std::endl;
|
||||
return (1);
|
||||
}
|
||||
signal(SIGINT, handleSig);
|
||||
signal(SIGQUIT, handleSig);
|
||||
try
|
||||
{
|
||||
Server server(port, argv[2]);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,9 @@ bool IrcMessage::hasParam(size_t index) const
|
|||
|
||||
const std::string &IrcMessage::param(size_t index) const
|
||||
{
|
||||
static const std::string empty;
|
||||
if (index >= _params.size())
|
||||
return (empty);
|
||||
return (_params[index]);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
#include "Server.hpp"
|
||||
|
||||
extern volatile sig_atomic_t g_stop;
|
||||
|
||||
void Server::start(void)
|
||||
{
|
||||
_serverFd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
|
@ -36,7 +38,7 @@ void Server::start(void)
|
|||
pollfd.events = POLLIN;
|
||||
pollfd.revents = 0;
|
||||
_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)
|
||||
|
|
@ -87,11 +89,29 @@ Server::~Server(void)
|
|||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
_users.erase(fd);
|
||||
for (size_t i = 0; i < _fds.size(); i++)
|
||||
|
|
@ -108,7 +128,7 @@ void Server::acceptNew(void)
|
|||
{
|
||||
int newFd = accept(_serverFd, NULL, NULL);
|
||||
if (newFd == -1)
|
||||
throw std::runtime_error(strerror(errno));
|
||||
return ;
|
||||
fcntl(newFd, F_SETFL, O_NONBLOCK);
|
||||
int flag = 1;
|
||||
setsockopt(newFd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag));
|
||||
|
|
@ -143,12 +163,16 @@ void Server::handleRecv(int fd)
|
|||
_users[fd].parseBuffer.append(buf, n);
|
||||
std::vector<IrcMessage> messages = _users[fd].parseBuffer.extractMessages();
|
||||
for (size_t i = 0; i < messages.size(); i++)
|
||||
{
|
||||
if (_users.find(fd) == _users.end())
|
||||
break ;
|
||||
dispatch(fd, messages[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::run(void)
|
||||
{
|
||||
while (true)
|
||||
while (!g_stop)
|
||||
{
|
||||
int ret = poll(_fds.data(), _fds.size(), -1);
|
||||
if (ret == -1)
|
||||
|
|
@ -163,8 +187,14 @@ void Server::run(void)
|
|||
removeUser(fd);
|
||||
i--;
|
||||
}
|
||||
else if ( _fds[i].revents & POLLIN)
|
||||
else if (_fds[i].revents & POLLIN)
|
||||
{
|
||||
size_t before = _fds.size();
|
||||
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)
|
||||
{
|
||||
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();
|
||||
for (; it != _users.end(); it++)
|
||||
{
|
||||
|
|
@ -233,8 +292,28 @@ void Server::handleNick(int fd, const IrcMessage &msg)
|
|||
return ;
|
||||
}
|
||||
}
|
||||
bool wasRegistered = _users[fd].isRegistered();
|
||||
std::string oldNick = _users[fd].nick;
|
||||
_users[fd].nick = newNick;
|
||||
_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)
|
||||
|
|
@ -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";
|
||||
broadcastToChannel(chanName, msg_rm, -1);
|
||||
chan.removeMember(fd);
|
||||
chan.removeOperator(fd);
|
||||
chan.removeInvited(fd);
|
||||
if (chan.memberCount() == 0)
|
||||
_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";
|
||||
broadcastToChannel(chanName, kick_msg, -1);
|
||||
chan.removeMember(targetFd);
|
||||
chan.removeOperator(targetFd);
|
||||
chan.removeInvited(targetFd);
|
||||
}
|
||||
|
||||
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 modeStr = msg.param(1);
|
||||
if (modeStr.size() < 2 || (modeStr[0] != '+' && modeStr[0] != '-'))
|
||||
return ;
|
||||
if (chanName.empty() || chanName[0] != '#')
|
||||
return ;
|
||||
if (_channels.find(chanName) == _channels.end())
|
||||
|
|
|
|||
Loading…
Reference in New Issue