~singpolyma/biboumi

020325dbb071f1735bceb80de9f982aefcd2de47 — Florent Le Coz 10 years ago 65601a9
[WIP] DummyIrcChannel
M src/bridge/bridge.cpp => src/bridge/bridge.cpp +20 -0
@@ 1,6 1,7 @@
#include <bridge/bridge.hpp>
#include <bridge/colors.hpp>
#include <xmpp/xmpp_component.hpp>
#include <irc/irc_message.hpp>
#include <network/poller.hpp>
#include <utils/encoding.hpp>
#include <logger/logger.hpp>


@@ 100,6 101,25 @@ IrcClient* Bridge::get_irc_client(const std::string& hostname)
bool Bridge::join_irc_channel(const Iid& iid, const std::string& username)
{
  IrcClient* irc = this->get_irc_client(iid.server, username);
  if (iid.chan.empty())
    { // Join the dummy channel
      if (irc->is_welcomed())
        {
          if (irc->get_dummy_channel().joined)
            return false;
          // Immediately simulate a message coming from the IRC server saying that we
          // joined the channel
          const IrcMessage join_message(irc->get_nick(), "JOIN", {""});
          irc->on_channel_join(join_message);
          const IrcMessage end_join_message(std::string(iid.server), "366",
                                            {irc->get_nick(),
                                                "", "End of NAMES list"});
          irc->on_channel_completely_joined(end_join_message);
        }
      else
          irc->get_dummy_channel().joining = true;
      return true;
    }
  if (irc->is_channel_joined(iid.chan) == false)
    {
      irc->send_join_command(iid.chan);

M src/irc/irc_channel.cpp => src/irc/irc_channel.cpp +6 -0
@@ 47,3 47,9 @@ void IrcChannel::remove_user(const IrcUser* user)
        }
    }
}

DummyIrcChannel::DummyIrcChannel():
  IrcChannel(),
  joining(false)
{
}

M src/irc/irc_channel.hpp => src/irc/irc_channel.hpp +32 -1
@@ 25,13 25,44 @@ public:
  IrcUser* find_user(const std::string& name) const;
  void remove_user(const IrcUser* user);

private:
protected:
  std::unique_ptr<IrcUser> self;
  std::vector<std::unique_ptr<IrcUser>> users;

private:
  IrcChannel(const IrcChannel&) = delete;
  IrcChannel(IrcChannel&&) = delete;
  IrcChannel& operator=(const IrcChannel&) = delete;
  IrcChannel& operator=(IrcChannel&&) = delete;
};

/**
 * A special channel that is not actually linked to any real irc
 * channel. This is just a channel representing a connection to the
 * server. If an user wants to maintain the connection to the server without
 * having to be on any irc channel of that server, he can just join this
 * dummy channel.
 * It’s not actually dummy because it’s useful and it does things, but well.
 */
class DummyIrcChannel: public IrcChannel
{
public:
  explicit DummyIrcChannel();

  /**
   * This flag is at true whenever the user wants to join this channel, but
   * he is not yet connected to the server. When the connection is made, we
   * check that flag and if it’s true, we inform the user that he has just
   * joined that channel.
   * If the user is already connected to the server when he tries to join
   * the channel, we don’t use that flag, we just join it immediately.
   */
  bool joining;
private:
  DummyIrcChannel(const DummyIrcChannel&) = delete;
  DummyIrcChannel(DummyIrcChannel&&) = delete;
  DummyIrcChannel& operator=(const DummyIrcChannel&) = delete;
  DummyIrcChannel& operator=(DummyIrcChannel&&) = delete;
};

#endif // IRC_CHANNEL_INCLUDED

M src/irc/irc_client.cpp => src/irc/irc_client.cpp +22 -1
@@ 280,7 280,11 @@ void IrcClient::set_and_forward_user_list(const IrcMessage& message)
void IrcClient::on_channel_join(const IrcMessage& message)
{
  const std::string chan_name = utils::tolower(message.arguments[0]);
  IrcChannel* channel = this->get_channel(chan_name);
  IrcChannel* channel;
  if (chan_name.empty())
    channel = &this->dummy_channel;
  else
    channel = this->get_channel(chan_name);
  const std::string nick = message.prefix;
  if (channel->joined == false)
    channel->set_self(nick);


@@ 394,6 398,18 @@ void IrcClient::on_welcome_message(const IrcMessage& message)
  for (const std::string& chan_name: this->channels_to_join)
    this->send_join_command(chan_name);
  this->channels_to_join.clear();
  // Indicate that the dummy channel is joined as well, if needed
  if (this->dummy_channel.joining)
    {
      // Simulate a message coming from the IRC server saying that we joined
      // the channel
      const IrcMessage join_message(this->get_nick(), "JOIN", {""});
      this->on_channel_join(join_message);
      const IrcMessage end_join_message(std::string(this->hostname), "366",
                                        {this->get_nick(),
                                            "", "End of NAMES list"});
      this->on_channel_completely_joined(end_join_message);
    }
}

void IrcClient::on_part(const IrcMessage& message)


@@ 624,3 640,8 @@ size_t IrcClient::number_of_joined_channels() const
{
  return this->channels.size();
}

DummyIrcChannel& IrcClient::get_dummy_channel()
{
  return this->dummy_channel;
}

M src/irc/irc_client.hpp => src/irc/irc_client.hpp +17 -0
@@ 194,6 194,14 @@ public:
   * Return the number of joined channels
   */
  size_t number_of_joined_channels() const;
  /**
   * Get a reference to the unique dummy channel
   */
  DummyIrcChannel& get_dummy_channel();

  const std::string& get_hostname() const { return this->hostname; }
  std::string get_nick() const { return this->current_nick; }
  bool is_welcomed() const { return this->welcomed; }

private:
  /**


@@ 217,12 225,21 @@ private:
   */
  std::unordered_map<std::string, std::unique_ptr<IrcChannel>> channels;
  /**
   * A single channel with a iid of the form "hostname" (normal channel have
   * an iid of the form "chan%hostname".
   */
  DummyIrcChannel dummy_channel;
  /**
   * A list of chan we want to join, but we need a response 001 from
   * the server before sending the actual JOIN commands. So we just keep the
   * channel names in a list, and send the JOIN commands for each of them
   * whenever the WELCOME message is received.
   */
  std::vector<std::string> channels_to_join;
  /**
   * This flag indicates that the server is completely joined (connection
   * has been established, we are authentified and we have a nick)
   */
  bool welcomed;
  /**
   * See http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt section 3.3

M src/test.cpp => src/test.cpp +1 -0
@@ 10,6 10,7 @@
#include <utils/tolower.hpp>
#include <utils/split.hpp>
#include <xmpp/jid.hpp>
#include <irc/iid.hpp>
#include <string.h>

#include <iostream>

M src/xmpp/xmpp_component.cpp => src/xmpp/xmpp_component.cpp +3 -2
@@ 290,8 290,9 @@ void XmppComponent::handle_presence(const Stanza& stanza)
                              error_type, error_name, "");
        });

  if (!iid.chan.empty() && !iid.server.empty())
    { // presence toward a MUC that corresponds to an irc channel
  if (!iid.server.empty())
    { // presence toward a MUC that corresponds to an irc channel, or a
      // dummy channel if iid.chan is empty
      if (type.empty())
        {
          const std::string own_nick = bridge->get_own_nick(iid);