00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef USE_PCH
00017 #include "sys.h"
00018 #include <sstream>
00019 #include <libcw/inet_debug_support.h>
00020 #include "debug.h"
00021 #endif
00022
00023 #include "ClientSession.h"
00024 #include "keys.h"
00025 #include "exceptions.h"
00026 #include "Identity.h"
00027 #include "identities_type.h"
00028 #include "Application.h"
00029 #include "Target.h"
00030 #include "Channel.h"
00031 #include "Nick.h"
00032 #include "is_channel.h"
00033 #include "Authentication.h"
00034 #include "is_channel.h"
00035 #include "exceptions.h"
00036
00037 void ClientSession::new_message_received(ClientMessageIn const& msg)
00038 {
00039 #ifdef CWDEBUG
00040
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
00052 Debug(if (suppress_debug_output) libcw_do.on());
00053
00054 return;
00055 }
00056 if (!has_identity())
00057 {
00058 if (msg.key() != keys::PASS)
00059 {
00060
00061 Debug(if (suppress_debug_output) libcw_do.on());
00062 Dout(dc::notice, "Received non-PASS message from client without Identity (" << msg << ')');
00063
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
00077 identities_type::iterator iter = Application::instance().identities().find(password);
00078 if (iter == Application::instance().identities().end())
00079 {
00080
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
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
00097
00098 start_queuing_messages();
00099
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
00118 Debug(if (suppress_debug_output) libcw_do.on());
00119 }
00120
00121 void ClientSession::process_message(ClientMessageIn const& msg)
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 }
00135
00136 void ClientSession::start_queuing_messages(void)
00137 {
00138 M_queue_messages = true;
00139 }
00140
00141 void ClientSession::stop_queuing_messages(DestructEventType const&)
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 }
00150
00151 void ClientSession::queue_message(ClientMessageIn const& msg)
00152 {
00153 DoutEntering(dc::debug, "ClientSession::queue_message(" << msg << ")");
00154 M_msg_queue.push_front(msg);
00155 }
00156
00157 void ClientSession::queue_msg_as_is(ServerMessageIn const& msg)
00158 {
00159 Prefix prefix(msg);
00160 MessageOut msgout(default_priority(msg.key()));
00161 queue_msg(msgout << prefix << msg.key() << msg.params(0));
00162 }
00163
00164 void ClientSession::queue_msg_me_as_is(ServerMessageIn const& msg)
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 }
00171
00172 void ClientSession::fatal_error(char const* error_msg)
00173 {
00174 DoutEntering(dc::debug, "ClientSession::fatal_error(\"" << error_msg << "\")");
00175 if (!must_be_removed())
00176 *this << "ERROR :" << error_msg << "\r\n";
00177
00178
00179 del();
00180 }
00181
00182 ClientSession::~ClientSession()
00183 {
00184 Dout(dc::objects, "Destructing ClientSession " << *this);
00185 if (has_identity())
00186 identity().reset_client_session(this);
00187
00188 user_answer_event_server.destroy_requests();
00189
00190 destruct_event_server.trigger(DestructEventType());
00191
00192 cancel_all_requests();
00193 }
00194
00195
00196 void ClientSession::add_private_target(boost::shared_ptr<Target> const& 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 }
00204
00205
00206 void ClientSession::del_private_target(std::string const& target_name)
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 }
00212
00213
00214 void ClientSession::create_private_target(std::string const& target_name, Network& network)
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 }
00239
00240 void ClientSession::queue_msg(MessageOut const& msgout)
00241 {
00242 DoutEntering(dc::debug, "ClientSession::queue_msg(" << msgout << ")");
00243
00244 msgout.write_to(*this);
00245 }
00246
00247 void ClientSession::new_client_nick_received(std::string const& nick)
00248 {
00249 M_in_nick = nick;
00250 if (!M_first_nick)
00251 {
00252
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);
00260 identity().authentication().received_nick();
00261 }
00262 M_first_nick = false;
00263 }
00264
00265 void ClientSession::serversession_lost(void)
00266 {
00267
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
00272 for (Channel::members_type::iterator member_iter = channel->members().begin(); member_iter != channel->members().end();)
00273 {
00274
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 }
00281
00282 boost::shared_ptr<Nick> ClientSession::get_nick(std::string const& nick_name, bool create)
00283 {
00284 ASSERT(is_nick(nick_name));
00285
00286
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
00292
00293 THROW_EXCEPTION(unknown_target(), "There is no client side nick \"" << nick_name << "\" on ClientSession " << *this);
00294 }