ircproxy  The Ultimate Cyborg

ClientSession Class Reference

#include <ClientSession.h>

Inheritance diagram for ClientSession:

Index< ClientSession > IdentityReference

List of all members.


Detailed Description

A client session, from connect till disconnect.

This class represents a client session: from that a client successfully connects to the application's listen socket, until the connection is closed or lost again.

Definition at line 45 of file ClientSession.h.


Public Types

typedef std::map< std::string,
boost::shared_ptr< Target >
, IRC_less
private_targets_type
 The type of the map with the private targets that the client has joined.
typedef target_hold_map_type joined_channels_type
 The type of M_joined_channels.

Public Member Functions

 ClientSession (void)
 Default constructor.
 ~ClientSession ()
 Destructor.
void fatal_error (char const *error_msg)
 A fatal error occured. Calling this function will terminate the ClientSession.
void new_client_nick_received (std::string const &nick)
 Called from Identity::new_client_message_received for NICK messages.
std::string const & client_in_nick (void) const
 Returns the last NICK as received from the client in this session.
std::string const & client_out_nick (void) const
 FIXME.
void process_message (ClientMessageIn const &msg)
 Decode message msg.
void queue_message (ClientMessageIn const &msg)
 Queue message msg.
void start_queuing_messages (void)
 Start queuing messages.
void stop_queuing_messages (DestructEventType const &)
 Stop queuing messages.
void add_private_target (boost::shared_ptr< Target > const &target)
 Add target to the private targets list.
void del_private_target (std::string const &target_name)
 Remove target_name from the private targets list.
private_targets_typeprivate_targets (void)
 Return reference to map with private targets.
private_targets_type const & private_targets (void) const
 Return const reference to map with private targets.
joined_channels_typejoined_channels (void)
 Return reference to map with known channels.
joined_channels_type const & joined_channels (void) const
 Return const reference to map with known channels.
void create_private_target (std::string const &target_name, Network &network)
 Check if target already exists, if not, create it and add it to our private targets map.
void queue_msg (MessageOut const &msgout)
 Send an output message to this session.
void queue_msg_as_is (ServerMessageIn const &msg)
 Pass message msg on to the client with default priority, without changing anything.
void queue_msg_me_as_is (ServerMessageIn const &msg)
 Pass message msg on to the client with default priority, changing only the target: my nick.
void serversession_lost (void)
 This function is called from ServerSession::session_lost().
boost::shared_ptr< Nickget_nick (std::string const &nick_name, bool create=false)
 Get or create a Nick for nick_name.

Public Attributes

UserAnswerEventServer user_answer_event_server
 The UserAnswer event server.
DestructEventServer destruct_event_server
 The DestructEvent event server.

Protected Member Functions

virtual void new_message_received (ClientMessageIn const &)
 Incoming event from ClientSessionInput.

Private Attributes

std::string M_in_nick
 The last NICK as received from the client in this session.
bool M_queue_messages
 Set if messages need to be queued instead of processed.
std::deque< ClientMessageInM_msg_queue
 The message queue.
bool M_first_nick
 Set before the first NICK message is received from the client.
private_targets_type M_private_targets
 Map with private targets that the client has joined.
joined_channels_type M_joined_channels
 Clientside lookup map for channels joined by this identity.

Member Typedef Documentation

typedef std::map<std::string, boost::shared_ptr<Target>, IRC_less> ClientSession::private_targets_type

The type of the map with the private targets that the client has joined.

Definition at line 49 of file ClientSession.h.

The type of M_joined_channels.

Definition at line 51 of file ClientSession.h.


Constructor & Destructor Documentation

ClientSession::ClientSession ( void   )  [inline]

Default constructor.

Definition at line 67 of file ClientSession.h.

References debug::channels::dc::objects.

00067                       : event_client_ct(), M_queue_messages(false), M_first_nick(true)
00068       { Dout(dc::objects, "Constructing ClientSession() " << *this); }

ClientSession::~ClientSession (  ) 

Destructor.

Definition at line 182 of file ClientSession.cc.

References destruct_event_server, IdentityReference::has_identity(), IdentityReference::identity(), debug::channels::dc::objects, Identity::reset_client_session(), and user_answer_event_server.

00183 {
00184   Dout(dc::objects, "Destructing ClientSession " << *this);
00185   if (has_identity())
00186     identity().reset_client_session(this);
00187   // First erase pending UserAnswer requests.
00188   user_answer_event_server.destroy_requests();
00189   // Then trigger the destruct event.
00190   destruct_event_server.trigger(DestructEventType());
00191   // Finally cancel all other event requests for this object.
00192   cancel_all_requests();
00193 }


Member Function Documentation

void ClientSession::fatal_error ( char const *  error_msg  ) 

A fatal error occured. Calling this function will terminate the ClientSession.

Definition at line 172 of file ClientSession.cc.

References DoutEntering.

Referenced by new_message_received(), and process_message().

00173 {
00174   DoutEntering(dc::debug, "ClientSession::fatal_error(\"" << error_msg << "\")");
00175   if (!must_be_removed())               // Only write one error at a time.
00176     *this << "ERROR :" << error_msg << "\r\n";
00177   // The next method sets 'must_be_removed()' to true,
00178   // flushes the error and deletes this object (non-blocking).
00179   del();
00180 }

void ClientSession::new_client_nick_received ( std::string const &  nick  ) 

Called from Identity::new_client_message_received for NICK messages.

Definition at line 247 of file ClientSession.cc.

References Identity::authentication(), default_priority(), IdentityReference::identity(), M_first_nick, M_in_nick, Identity::mynick(), ServerSession::queue_msg(), Authentication::received_nick(), ServerSession::send_nick_write_event(), and Identity::server_session().

Referenced by Identity::new_client_message_received().

00248 {
00249   M_in_nick = nick;
00250   if (!M_first_nick)
00251   {
00252     // Client tries to change nick name.
00253     PseudoMessageOut pseudo_msg(default_priority(keys::NICK));
00254     pseudo_msg.writeEventRequest(identity().server_session(), &ServerSession::send_nick_write_event, M_in_nick);
00255     identity().server_session().queue_msg(pseudo_msg);
00256   }
00257   else
00258   {
00259     identity().mynick()->set_in_nick(*this, M_in_nick);         // Initialize out client-side nick name.
00260     identity().authentication().received_nick();
00261   }
00262   M_first_nick = false;
00263 }

std::string const& ClientSession::client_in_nick ( void   )  const [inline]

Returns the last NICK as received from the client in this session.

Definition at line 80 of file ClientSession.h.

References M_in_nick.

Referenced by QuestionTarget::new_client_message_received().

00080 { return M_in_nick; }

std::string const& ClientSession::client_out_nick ( void   )  const [inline]

void ClientSession::process_message ( ClientMessageIn const &  msg  ) 

Decode message msg.

Definition at line 121 of file ClientSession.cc.

References edragon::caught(), DoutEntering, fatal_error(), IdentityReference::identity(), Identity::new_client_message_received(), and FatalError::what().

Referenced by new_message_received(), and stop_queuing_messages().

00122 {
00123   DoutEntering(dc::debug, "ClientSession::process_message(" << msg << ")");
00124   try
00125   {
00126     identity().new_client_message_received(msg);
00127   }
00128   catch (FatalError& error)
00129   {
00130     Debug(edragon::caught(error));
00131     fatal_error(error.what());
00132     return;
00133   }
00134 }

void ClientSession::queue_message ( ClientMessageIn const &  msg  ) 

Queue message msg.

Definition at line 151 of file ClientSession.cc.

References DoutEntering, and M_msg_queue.

Referenced by new_message_received().

00152 {
00153   DoutEntering(dc::debug, "ClientSession::queue_message(" << msg << ")");
00154   M_msg_queue.push_front(msg);
00155 }

void ClientSession::start_queuing_messages ( void   ) 

Start queuing messages.

Definition at line 136 of file ClientSession.cc.

References M_queue_messages.

Referenced by new_message_received().

00137 {
00138   M_queue_messages = true;
00139 }

void ClientSession::stop_queuing_messages ( DestructEventType const &   ) 

Stop queuing messages.

Definition at line 141 of file ClientSession.cc.

References M_msg_queue, M_queue_messages, and process_message().

Referenced by new_message_received().

00142 {
00143   while (!M_msg_queue.empty())
00144   {
00145     process_message(M_msg_queue.back());
00146     M_msg_queue.pop_back();
00147   }
00148   M_queue_messages = false;
00149 }

void ClientSession::add_private_target ( boost::shared_ptr< Target > const &  target  ) 

Add target to the private targets list.

Definition at line 196 of file ClientSession.cc.

References ASSERT, and M_private_targets.

Referenced by Identity::notice_target().

00197 {
00198 #if defined(DEBUG) || defined(CWDEBUG)
00199   std::pair<private_targets_type::iterator, bool> result =
00200 #endif
00201       M_private_targets.insert(private_targets_type::value_type(target->in_name(*this), target));
00202   ASSERT(result.second);
00203 }

void ClientSession::del_private_target ( std::string const &  target_name  ) 

Remove target_name from the private targets list.

Definition at line 206 of file ClientSession.cc.

References ASSERT, and M_private_targets.

Referenced by ServerConnection::do_connect(), and PrivateTarget::new_client_message_received().

00207 {
00208   private_targets_type::iterator iter = M_private_targets.find(target_name);
00209   ASSERT(iter != M_private_targets.end());
00210   M_private_targets.erase(iter);
00211 }

private_targets_type& ClientSession::private_targets ( void   )  [inline]

Return reference to map with private targets.

Definition at line 101 of file ClientSession.h.

References M_private_targets.

Referenced by Target::clientside_get_channel(), get_nick(), Identity::new_client_message_received(), and Identity::notice_target().

00101 { return M_private_targets; }

private_targets_type const& ClientSession::private_targets ( void   )  const [inline]

Return const reference to map with private targets.

Definition at line 104 of file ClientSession.h.

References M_private_targets.

00104 { return M_private_targets; }

joined_channels_type& ClientSession::joined_channels ( void   )  [inline]

joined_channels_type const& ClientSession::joined_channels ( void   )  const [inline]

Return const reference to map with known channels.

Definition at line 110 of file ClientSession.h.

References M_joined_channels.

00110 { return M_joined_channels; }

void ClientSession::create_private_target ( std::string const &  target_name,
Network network 
)

Check if target already exists, if not, create it and add it to our private targets map.

Create a new target target_name and add it to the private targets map, unless it already exists.

Definition at line 214 of file ClientSession.cc.

References ASSERT, DoutEntering, IdentityReference::identity(), is_channel(), is_nick(), Network::is_private(), and M_private_targets.

Referenced by QuestionTarget::create_channel_and_ask_question().

00215 {
00216   DoutEntering(dc::debug, "ClientSession::create_private_target(\"" << target_name << "\", " << network << ')');
00217   ASSERT(network.is_private());
00218   private_targets_type::iterator iter = M_private_targets.find(target_name);
00219   if (iter == M_private_targets.end())
00220   {
00221     Dout(dc::debug, "Not found. Creating new private target.");
00222     if (is_channel(target_name))
00223     {
00224       boost::shared_ptr<Target> new_target(NEW(Channel(identity(), target_name, network, 0)));
00225       M_private_targets.insert(private_targets_type::value_type(target_name, new_target));
00226     }
00227     else
00228     {
00229       ASSERT(is_nick(target_name));
00230       boost::shared_ptr<Target> new_target(NEW(Nick(*this, target_name, network)));
00231       M_private_targets.insert(private_targets_type::value_type(target_name, new_target));
00232     }
00233   }
00234 #ifdef CWDEBUG
00235   else
00236     Dout(dc::debug, "Found: " << *iter);
00237 #endif
00238 }

void ClientSession::queue_msg ( MessageOut const &  msgout  ) 

Send an output message to this session.

Definition at line 240 of file ClientSession.cc.

References DoutEntering, and MessageOut::write_to().

Referenced by Identity::new_client_message_received(), ServerSession::new_message_received(), Identity::new_server_message_received(), Channel::new_server_message_received(), queue_msg_as_is(), and queue_msg_me_as_is().

00241 {
00242   DoutEntering(dc::debug, "ClientSession::queue_msg(" << msgout << ")");
00243   // No need to queue anything (yet?), just send it to the client.
00244   msgout.write_to(*this);
00245 }

void ClientSession::queue_msg_as_is ( ServerMessageIn const &  msg  ) 

Pass message msg on to the client with default priority, without changing anything.

Definition at line 157 of file ClientSession.cc.

References default_priority(), MessageIn::key(), MessageIn::params(), and queue_msg().

00158 {
00159   Prefix prefix(msg);
00160   MessageOut msgout(default_priority(msg.key()));
00161   queue_msg(msgout << prefix << msg.key() << msg.params(0));
00162 }

void ClientSession::queue_msg_me_as_is ( ServerMessageIn const &  msg  ) 

Pass message msg on to the client with default priority, changing only the target: my nick.

Definition at line 164 of file ClientSession.cc.

References ASSERT, default_priority(), IdentityReference::identity(), MessageIn::key(), Identity::mynick(), MessageIn::param(), MessageIn::params(), queue_msg(), and ServerMessageIn::server_session().

Referenced by ServerSession::new_message_received().

00165 {
00166   ASSERT(msg.param(0) == identity().mynick()->in_name(msg.server_session()));
00167   Prefix prefix(msg);
00168   MessageOut msgout(default_priority(msg.key()));
00169   queue_msg(msgout << prefix << msg.key() << identity().mynick() << msg.params(1));
00170 }

void ClientSession::serversession_lost ( void   ) 

This function is called from ServerSession::session_lost().

Definition at line 265 of file ClientSession.cc.

References Identity::do_quit(), IdentityReference::identity(), and joined_channels().

Referenced by ServerConnection::session_lost().

00266 {
00267   // Run over all channels that we're on.
00268   for (joined_channels_type::iterator channel_iter = joined_channels().begin(); channel_iter != joined_channels().end(); ++channel_iter)
00269   {
00270     boost::shared_ptr<Channel> const& channel(boost::static_pointer_cast<Channel>(channel_iter->second));
00271     // Run over all members.
00272     for (Channel::members_type::iterator member_iter = channel->members().begin(); member_iter != channel->members().end();)
00273     {
00274       // QUIT all members except myself.
00275       boost::shared_ptr<Nick> const& nick((member_iter++)->second.get_nick());
00276       if (!nick->is_me())
00277         identity().do_quit(nick, "ircproxy lost connection");
00278     }
00279   }
00280 }

boost::shared_ptr< Nick > ClientSession::get_nick ( std::string const &  nick_name,
bool  create = false 
)

Get or create a Nick for nick_name.

Definition at line 282 of file ClientSession.cc.

References ASSERT, is_nick(), private_targets(), and THROW_EXCEPTION.

Referenced by Identity::new_client_message_received().

00283 {
00284   ASSERT(is_nick(nick_name));
00285 
00286   // First search in the map with private targets.
00287   private_targets_type::const_iterator priv_iter = private_targets().find(nick_name);
00288   if (priv_iter != private_targets().end())
00289     return boost::static_pointer_cast<Nick>(priv_iter->second);
00290 
00291   // FIXME
00292 
00293   THROW_EXCEPTION(unknown_target(), "There is no client side nick \"" << nick_name << "\" on ClientSession " << *this);
00294 }

void ClientSession::new_message_received ( ClientMessageIn const &  msg  )  [protected, virtual]

Incoming event from ClientSessionInput.

Definition at line 37 of file ClientSession.cc.

References destruct_event_server, DoutEntering, fatal_error(), IdentityReference::has_identity(), IdentityReference::identity(), MessageIn::key(), M_queue_messages, MessageIn::param(), process_message(), queue_message(), Identity::set_client_session(), Identity::set_hostname(), IdentityReference::set_identity(), start_queuing_messages(), and stop_queuing_messages().

00038 {
00039 #ifdef CWDEBUG
00040   // Suppress all debug output related to PING messages.
00041   bool suppress_debug_output =
00042       (msg.key() == keys::PING && Application::instance().suppress_ping()) ||
00043       (msg.key() == keys::WHO && Application::instance().suppress_who());
00044   Debug(if (suppress_debug_output) libcw_do.off());
00045 #endif
00046 
00047   DoutEntering(dc::debug, "ClientSession::new_message_received(" << msg << ")");
00048   if (must_be_removed())
00049   {
00050     Dout(dc::debug, "Do nothing, ClientSession is marked for removal.");
00051     // Turn debug output on again, if it was suppressed.
00052     Debug(if (suppress_debug_output) libcw_do.on());
00053     // Skip message.
00054     return;
00055   }
00056   if (!has_identity())
00057   {
00058     if (msg.key() != keys::PASS)
00059     {
00060       // Turn debug output on again, if it was suppressed.
00061       Debug(if (suppress_debug_output) libcw_do.on());
00062       Dout(dc::notice, "Received non-PASS message from client without Identity (" << msg << ')');
00063       // Error. The first message from a client must ALWAYS be a PASS.
00064       fatal_error("Send PASS first.");
00065       return;
00066     }
00067     Dout(dc::debug, "Received PASS: " << msg);
00068     std::string password(msg.param(0));
00069     if (password.empty())
00070     {
00071       fatal_error("Empty password.");
00072       return;
00073     }
00074     else
00075     {
00076       // Find or create Identity.
00077       identities_type::iterator iter = Application::instance().identities().find(password);
00078       if (iter == Application::instance().identities().end())
00079       {
00080         // Create new Identity.
00081         Identity identity(password);
00082         set_identity(&Application::instance().identities().
00083             insert(std::pair<std::string, Identity>(password, identity)).first->second);
00084         Dout(dc::debug, "Created a new Identity.");
00085       }
00086       else
00087       {
00088         set_identity(&iter->second);
00089         // If the identity already has another ClientSession, kill that.
00090         if (identity().has_client_session())
00091         {
00092           ClientSession& old_client_session(identity().client_session());
00093           std::ostringstream error_msg;
00094           error_msg << "Received new client connection from " << old_client_session.remote_ip();
00095           old_client_session.fatal_error(error_msg.str().c_str());
00096           // Wait till the old session is actually destructed before processing
00097           // messages from this connection.
00098           start_queuing_messages();
00099           // Request stop_queuing_messages to be called when old_client_session is destructed.
00100           old_client_session.destruct_event_server(*this, &ClientSession::stop_queuing_messages);
00101         }
00102       }
00103       identity().set_client_session(this);
00104       if (identity().hostname() != unknown_hostname)
00105       {
00106         std::ostringstream buf;
00107         buf << remote_ip();
00108         identity().set_hostname(buf.str());
00109       }
00110     }
00111   }
00112   if (!M_queue_messages)
00113     process_message(msg);
00114   else
00115     queue_message(msg);
00116 
00117   // Turn debug output on again, if it was suppressed.
00118   Debug(if (suppress_debug_output) libcw_do.on());
00119 }


Member Data Documentation

std::string ClientSession::M_in_nick [private]

The last NICK as received from the client in this session.

Definition at line 54 of file ClientSession.h.

Referenced by client_in_nick(), client_out_nick(), and new_client_nick_received().

Set if messages need to be queued instead of processed.

Definition at line 55 of file ClientSession.h.

Referenced by new_message_received(), start_queuing_messages(), and stop_queuing_messages().

The message queue.

Definition at line 56 of file ClientSession.h.

Referenced by queue_message(), and stop_queuing_messages().

Set before the first NICK message is received from the client.

Definition at line 57 of file ClientSession.h.

Referenced by new_client_nick_received().

Map with private targets that the client has joined.

Definition at line 58 of file ClientSession.h.

Referenced by add_private_target(), create_private_target(), del_private_target(), and private_targets().

Clientside lookup map for channels joined by this identity.

Definition at line 59 of file ClientSession.h.

Referenced by joined_channels().

The DestructEvent event server.

Definition at line 63 of file ClientSession.h.

Referenced by new_message_received(), and ~ClientSession().


The documentation for this class was generated from the following files:

Copyright © 2005-2007 Carlo Wood.  All rights reserved.