faboussard / 42-irc

3 stars 1 forks source link

Invalid read error when a client tries to rejoin a channel after quitting #28

Closed ysengoku closed 2 weeks ago

ysengoku commented 2 weeks ago

Invalid read error when a client tries to rejoin a channel after quitting without sort from it.

e.g.

Client : JOIN #channel
Client : QUIT  // without part from `#channel`
--- Client reconnects
Client:  JOIN #channel  // Invalid read occurs here
faboussard commented 2 weeks ago

comment tu reconnectes ? tu fais controle C apres le quit ?

ici jai juste fait quit, puis join , vu que quit ne ma pas deconnectee . et dans ce cas pas d erreur.

quit
join #s
nc: write failed (0/2): Broken pipe
ysengoku commented 2 weeks ago

Le test etait comme ceci:

nc -C localhost 6667
PASS pass
NICK test1
USER a a a :a
// Client test is connected.

JOIN #42
// Client joins to channel #42

QUIT
// Client quits Server without PART from the channel #42

[control C] to exit from nc

nc -C localhost 6667
PASS pass
NICK test2
USER a a a :a
// Another client test2 is connected via the same fd as Client test1

JOIN #42
// Join to the existing channel in which Client test1 had participated.

Je crois que nous devons delete des pointers sur Client de tous les channels losqu'ils quittent sans partir des channels. Je vais tester cela.

ysengoku commented 2 weeks ago

J'ai ajoute cela dans Server.cpp void Server::clearClient(int fd) Ca a l'air de fonctionner de mon cote. Pouvez-vous tester si vous voulez @faboussard @melobern ?

Server.cpp

void Server::clearClient(int fd) {
  closeClient(fd);

  for (size_t i = 0; i < _pollFds.size(); i++) {
    if (_pollFds[i].fd == fd) {
      _pollFds.erase(_pollFds.begin() + i);
      break;
    }
  }
/* ----- Add this --------------------------------------------------------- */
  // Check if the client is in channels. If yes, remove it from the channels.
  if (_clients.at(fd).getChannelsCount() > 0) {
    channelsMap::iterator itEnd = _channels.end();
    for (channelsMap::iterator it = _channels.begin(); it != itEnd; ++it) {
      if (it->second.getChannelClients().find(fd) !=
          it->second.getChannelClients().end())
        it->second.removeClientFromChannelMap(&_clients.at(fd));
      if (it->second.getChannelOperators().find(fd) !=
          it->second.getChannelOperators().end())
        it->second.removeOperator(&_clients.at(fd));
    }
  }
 /*---------------------------------------------------------------------------- */
  _clients.erase(fd);
}