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 "debug.h"
00020 #endif
00021 
00022 #include "MessageIn.h"
00023 #include "Authentication.h"
00024 #include "NoticeTarget.h"
00025 #include "keys.h"
00026 #include "Identity.inl"
00027 #include "Channel.h"
00028 #include "Nick.h"
00029 #include "PersistXML.h"
00030 #include "is_channel.h"
00031 #include "ClientSession.h"
00032 #include "Matcher.h"
00033 #include "Application.h"
00034 #include "WhoRequest.h"
00035 
00036 
00037 
00038 
00039 
00040 void Identity::pass_as_is_to(MessageIn const& msg, std::ostream& os)
00041 {
00042   if (msg.has_prefix())
00043     os << ':' << msg.prefix_str() << ' ';
00044   if (msg.is_numeric())
00045     os << msg.numeric();
00046   else
00047     os << msg.uppercase_command();
00048   int number_of_parameters = msg.params_size();
00049   for (int param = 0; param < number_of_parameters; ++param)
00050   {
00051     os << ' ';
00052     if (param == number_of_parameters - 1)
00053       os << ':';
00054     os << msg.param(param);
00055   }
00056   os << "\r\n";
00057 }
00058 
00059 
00060 
00061 
00062 
00063 void Identity::pass_as_is_to_server(ClientMessageIn const& msg)
00064 {
00065   bool blocked = true;
00066   switch (msg.key())
00067   {
00068     using namespace keys;
00069     case WHO:                   
00070     case WHOIS:                 
00071     case WHOWAS:                
00072       blocked = false;
00073       break;
00074     default:
00075       break;
00076   }
00077   if (blocked && server_connection().state() < real_nick_sent)
00078     THROW_EXCEPTION(FatalError("Message to be passed as-is is blocked!"),
00079         "Identity::pass_as_is_to_server(" << msg << ") called while server connection in state " << server_connection().state() << '!');
00080   pass_as_is_to(msg, server_session());
00081 }
00082 
00083 
00084 
00085 
00086 
00087 void Identity::pass_as_is_to_client(ServerMessageIn const& msg)
00088 {
00089   pass_as_is_to(msg, client_session());
00090 }
00091 
00092 void Identity::new_client_message_received(ClientMessageIn const& msg)
00093 {
00094   DoutEntering(dc::debug, "Identity::new_client_message_received(" << msg << ")");
00095 
00096   switch (msg.key())
00097   {
00098     using namespace keys;
00099     case PASS:                  
00100       Authentication::get(this, M_authentication);
00101       M_authentication->decode_pass(msg);
00102       break;
00103     case USER:                  
00104       if (M_ident == unknown_ident)     
00105         M_ident = msg.param(0);
00106       M_real_name = msg.param(3);
00107       Authentication::get(this, M_authentication);
00108       M_authentication->decode_user(msg);
00109       break;
00110     case PING:                  
00111     {
00112       std::string server_name(server_connection().has_server() ? server_connection().server()->get_irc_name() : "noserver.pong.org");
00113       Prefix prefix(server_name);
00114       MessageOut msgout(default_priority(keys::PONG));
00115       client_session().queue_msg(msgout << prefix << keys::PONG << server_name << msg.params(0));
00116       break;
00117     }
00118     case SILENCE:               
00119     {
00120       
00121       
00122       server_session().queue_msg_as_is(msg);
00123       break;
00124     }
00125     case OPER:                  
00126     case MAP:
00127     case WALLOPS:
00128     case WALLUSERS:
00129     {
00130       
00131       
00132       server_session().queue_msg_as_is(msg);
00133       break;
00134     }
00135     case STATS:                 
00136     case VERSION:
00137     {
00138       
00139       
00140       server_session().queue_msg_as_is(msg);
00141       break;
00142     }
00143     case WHO:                   
00144     {
00145       WhoRequest who_request(msg.client_session(), (msg.params_size() >= 3) ? msg.param(2) : msg.param(0), msg.param(1));
00146       if (msg.params().size() >= 1 && who_request.options().matches_against_channel() && is_channel(who_request.mask()))
00147       {
00148         
00149         ClientSession::private_targets_type::iterator priv_iter = client_session().private_targets().find(who_request.mask());
00150         if (priv_iter != client_session().private_targets().end())
00151         {
00152           boost::static_pointer_cast<PrivateTarget>(priv_iter->second)->handle_who(who_request);
00153           break;
00154         }
00155       }
00156       
00157       PseudoMessageOut pseudo_msg(default_priority(keys::WHO), safe_query);
00158       pseudo_msg.writeEventRequest(server_session(), &ServerSession::send_who_write_event, who_request);
00159       server_session().queue_msg(pseudo_msg);
00160       break;
00161     }
00162     case WHOIS:                 
00163     case WHOWAS:                
00164     case LIST:                  
00165     {
00166       
00167       Prefix prefix(msg);
00168       
00169       MessageOut msgout(default_priority(msg.key()));
00170       server_session().queue_msg(msgout << prefix << msg.key() << msg.params(0));
00171       break;
00172     }
00173     case LINKS:                 
00174       break;
00175     case NICK:                  
00176       
00177       msg.client_session().new_client_nick_received(msg.param(0));
00178       break;
00179     case QUIT:                  
00180       break;
00181     case KILL:                  
00182     {
00183       Prefix prefix(msg);
00184       MessageOut msgout(default_priority(msg.key()));
00185       try
00186       {
00187         
00188         boost::shared_ptr<Target> nick = msg.client_session().get_nick(msg.param(0));
00189         server_session().queue_msg(msgout << prefix << msg.key() << nick << msg.params(1));
00190       }
00191       catch(unknown_target& error)
00192       {
00193         Debug(edragon::caught(error));
00194         server_session().queue_msg(msgout << prefix << msg.key() << msg.params(0));
00195       }
00196       break;
00197     }
00198     case MODE:                  
00199     case PRIVMSG:               
00200     case NOTICE:                
00201     {
00202       if (!msg.params().empty())
00203       {
00204         char c = *msg.params().front().start();
00205         if (c != '#' && c != '&')
00206         {
00207           if (msg.key() == MODE)
00208           {
00209             
00210             
00211             ASSERT(msg.param(0) == mynick()->in_name(client_session())); 
00212             Prefix prefix(msg);
00213             MessageOut msgout(default_priority(msg.key()));
00214             server_session().queue_msg(msgout << prefix << msg.key() << mynick() << msg.params(1));
00215             break;
00216           }
00217           else
00218           {
00219             try
00220             {
00221               
00222               msg.client_session().get_nick(msg.param(0))->new_client_message_received(msg);
00223             }
00224             catch(unknown_target& error)
00225             {
00226               Debug(edragon::caught(error));
00227               
00228               
00229               
00230               server_session().queue_msg_as_is(msg);
00231             }
00232           }
00233           break;
00234         }
00235       }
00236       
00237     }
00238     case INVITE:                
00239     case CPRIVMSG:              
00240     case CNOTICE:               
00241     case JOIN:                  
00242     case PART:                  
00243     case KICK:                  
00244     case NAMES:                 
00245     case TOPIC:                 
00246       try
00247       {
00248         
00249         Target::clientside_get_channel(*this, msg.param(0))->new_client_message_received(msg);
00250       }
00251       catch(unknown_target& error)
00252       {
00253         Debug(edragon::caught(error));
00254         
00255         
00256         server_session().queue_msg_as_is(msg);
00257       }
00258       break;
00259   }
00260 }
00261 
00262 void Identity::do_quit(boost::shared_ptr<Nick> nick, std::string const& quit_message)
00263 {
00264   ASSERT(!nick->is_me());
00265   Prefix prefix(nick);
00266   MessageOut msgout(default_priority(keys::QUIT));
00267   client_session().queue_msg(msgout << prefix << keys::QUIT << JustInTimeLast(quit_message));
00268   NickData::common_channels_type& common_channels(nick->data().common_channels());
00269   Dout(dc::maps, "QUIT by " << nick << " who is on " << common_channels.size() << " common channels.");
00270   NickData::common_channels_type::iterator iter = common_channels.begin();
00271   while (iter != common_channels.end())
00272   {
00273     
00274     (iter++)->second.lock()->sub_joined_nick(nick);
00275   }
00276 }
00277 
00278 void Identity::new_server_message_received(ServerMessageIn const& msg)
00279 {
00280   ASSERT(!debug::secondary_connection);
00281   DoutEntering(dc::debug, "Identity::new_server_message_received(" << msg << ")");
00282 
00283   switch (msg.key())
00284   {
00285     using namespace keys;
00286     case 315:   
00287     {
00288       Prefix prefix(msg);
00289       MessageOut msgout(default_priority(msg.key()));
00290       client_session().queue_msg(msgout << prefix << msg.key() << mynick() << msg.params(1));
00291 #ifdef CWDEBUG
00292       WhoRequest who_request(server_session().current_who_request());
00293       ASSERT(who_request.mask() == msg.param(1));
00294 #endif
00295       server_session().pop_who_request();
00296       break;
00297     }
00298     case 324:
00299     {
00300       Prefix prefix(msg);
00301       MessageOut msgout(default_priority(msg.key()));
00302       
00303       std::string my_nick_name(msg.param(0));
00304       ASSERT(my_nick_name == mynick()->in_name(msg.server_session()));
00305       
00306       msgout << prefix << msg.key() << mynick();
00307       
00308       try
00309       {
00310         boost::shared_ptr<Channel> channel(Target::serverside_get_channel(*this, msg.param(1)));
00311         msgout << channel;
00312       }
00313       catch (unknown_target& error)
00314       {
00315         Debug(edragon::caught(error));   
00316         msgout << msg.param(1);
00317       }
00318       msgout << msg.params(2);
00319       
00320       client_session().queue_msg(msgout);
00321       break;
00322     }
00323     case 329:   
00324     {
00325       Prefix prefix(msg);
00326       MessageOut msgout(default_priority(msg.key()));
00327       
00328       std::string my_nick_name(msg.param(0));
00329       ASSERT(my_nick_name == mynick()->in_name(msg.server_session()));
00330       
00331       msgout << prefix << msg.key() << mynick();
00332       time_t creation_time = atol(msg.param(2).c_str());
00333       try
00334       {
00335         boost::shared_ptr<Channel> channel(Target::serverside_get_channel(*this, msg.param(1)));
00336         channel->set_creation_time(creation_time);
00337         msgout << channel;
00338       }
00339       catch (unknown_target& error)
00340       {
00341         Debug(edragon::caught(error));   
00342         msgout << msg.param(1);
00343       }
00344       msgout << creation_time;
00345       
00346       client_session().queue_msg(msgout);
00347       break;
00348     }
00349     case 352:   
00350     {
00351       
00352       WhoRequest who_request(server_session().current_who_request());
00353       Dout(dc::notice, "Decoding numeric 352 for WHO request " << who_request);
00354       
00355       
00356       
00357       
00358       
00359       
00360       
00361       
00362       
00363       Prefix prefix(msg);
00364       MessageOut msgout(default_priority(msg.key()));
00365       
00366       std::string my_nick_name(msg.param(0));
00367       ASSERT(my_nick_name == mynick()->in_name(msg.server_session()));
00368       
00369       msgout << prefix << msg.key() << mynick();
00370       try
00371       {
00372         boost::shared_ptr<Channel> channel(Target::serverside_get_channel(*this, msg.param(1)));
00373         msgout << channel;
00374       }
00375       catch (unknown_target& error)
00376       {
00377         Debug(edragon::caught(error));   
00378         msgout << msg.param(1); 
00379       }
00380       std::string username(msg.param(2));
00381       std::string hostname(msg.param(3));
00382       std::string servername(msg.param(4));
00383       std::string flags(msg.param(6));
00384       std::string realname(msg.param(7));
00385       int hopcount = atoi(realname.c_str());
00386       realname = realname.substr(realname.find(' ') + 1);
00387       msgout << username << hostname << servername;
00388       try
00389       {
00390         boost::shared_ptr<Nick> nick(msg.server_session().get_nick(msg.param(5)));
00391         msgout << nick;
00392         nick->data().set_username(username);
00393         nick->data().set_hostname(hostname);
00394         nick->data().set_realname(realname);
00395         nick->data().set_hopcount(hopcount);
00396         nick->data().set_flags(Flags(network(), flags));
00397       }
00398       catch(unknown_target& error)
00399       {
00400         Debug(edragon::caught(error));   
00401         msgout << msg.param(5);
00402       }
00403       msgout << flags << msg.params(7);
00404       
00405       client_session().queue_msg(msgout);
00406       break;
00407     }
00408     case 354:   
00409     {
00410       
00411       WhoRequest who_request(server_session().current_who_request());
00412       Dout(dc::notice, "Decoding numeric 354 for WHO request " << who_request);
00413       
00414       
00415       
00416       
00417       
00418       
00419       
00420       
00421       
00422       
00423       
00424       
00425       
00426 
00427       Prefix prefix(msg);
00428       MessageOut msgout(default_priority(msg.key()));
00429       
00430       std::string my_nick_name(msg.param(0));
00431       ASSERT(my_nick_name == mynick()->in_name(msg.server_session()));
00432       
00433       msgout << prefix << msg.key() << mynick();
00434 
00435       int n = 0;
00436       
00437       for (unsigned int field = 1; field < field_percentage; field <<= 1)
00438       {
00439         if ((who_request.options().fields() & field))
00440         {
00441           
00442           ++n;
00443           
00444           if (field == field_c)         
00445           {
00446             try
00447             {
00448               boost::shared_ptr<Channel> channel(Target::serverside_get_channel(*this, msg.param(n)));
00449               msgout << channel;
00450             }
00451             catch (unknown_target& error)
00452             {
00453               Debug(edragon::caught(error));   
00454               msgout << msg.param(n); 
00455             }
00456           }
00457           else if (field == field_n)    
00458           {
00459             try
00460             {
00461               boost::shared_ptr<Nick> nick(msg.server_session().get_nick(msg.param(n)));
00462               msgout << nick;
00463               int n2 = 0;
00464               for (unsigned int field2 = 1; field2 < field_percentage; field2 <<= 1)
00465                 if ((who_request.options().fields() & field2))
00466                 {
00467                   ++n2;
00468                   switch(field2)
00469                   {
00470                     case field_u:
00471                       nick->data().set_username(msg.param(n2));
00472                       break;
00473                     case field_h:
00474                       nick->data().set_hostname(msg.param(n2));
00475                       break;
00476                     case field_i:
00477                       nick->data().set_ip(IPNumber(msg.param(n2)));
00478                       break;
00479                     case field_r:
00480                       nick->data().set_realname(msg.param(n2));
00481                       break;
00482                     case field_d:
00483                       nick->data().set_hopcount(atoi(msg.param(n2).c_str()));
00484                       break;
00485                     case field_f:
00486                       nick->data().set_flags(Flags(network(), msg.param(n2)));
00487                       break;
00488                     case field_s:
00489                       nick->data().set_servername(msg.param(n2));
00490                       break;
00491                     case field_l:
00492                       nick->data().set_idletime(atoi(msg.param(n2).c_str()));
00493                       break;
00494                     case field_a:
00495                       nick->data().set_accountname(msg.param(n2));
00496                       break;
00497                   }
00498                 }
00499             }
00500             catch(unknown_target& error)
00501             {
00502               Debug(edragon::caught(error));   
00503               msgout << msg.param(n);
00504             }
00505           }
00506           else
00507             msgout << msg.param(n);
00508         }
00509       }
00510       
00511       client_session().queue_msg(msgout);
00512       break;
00513     }
00514     case 353:   
00515     {
00516       
00517       Prefix prefix(msg);
00518       
00519       MessageOut msgout(default_priority(msg.key()));
00520       
00521       boost::shared_ptr<Channel> channel(Target::serverside_get_channel(*this, msg.param(2)));
00522       bool received_first_names = channel->received_names();
00523       
00524       std::string my_nick_name(msg.param(0));
00525       ASSERT(my_nick_name == mynick()->in_name(msg.server_session()));
00526       
00527       msgout << prefix << msg.key() << mynick() << msg.param(1) << channel;
00528       
00529       MsgPart names_list(msg.params(3));
00530       char const* list_start = names_list.start();
00531       if (*list_start == ':')
00532         ++list_start;
00533       char const* const list_end = names_list.end();
00534       char const* word_end;
00535       for (char const* word_start = list_start; word_start < list_end; word_start = word_end + 1)
00536       {
00537         ASSERT(*word_start != ' ');
00538         for (word_end = word_start; word_end < list_end && *word_end != ' '; ++word_end);
00539         std::string param(word_start, word_end - word_start);
00540         if (!IsNickChar(*word_start))
00541         {
00542           ASSERT(*word_start == '@' || *word_start == '+');
00543           std::string nick_name(word_start + 1, word_end - word_start - 1);
00544           boost::shared_ptr<Nick> nick;
00545           if (received_first_names)
00546             nick = Target::get_joined_nick(*this, nick_name, channel);
00547           else if (nick_name == my_nick_name)   
00548             nick = mynick();
00549           else
00550             nick = Target::add_joined_nick(*this, nick_name, channel);
00551           msgout << *word_start << JustInTimeCatenate(nick);
00552         }
00553         else
00554         {
00555           std::string nick_name(word_start, word_end - word_start);
00556           boost::shared_ptr<Nick> nick;
00557           if (received_first_names)
00558             nick = Target::get_joined_nick(*this, nick_name, channel);
00559           else if (nick_name == my_nick_name)   
00560             nick = mynick();
00561           else
00562             nick = Target::add_joined_nick(*this, nick_name, channel);
00563           msgout << nick;
00564         }
00565       }
00566       client_session().queue_msg(msgout);
00567       break;
00568     }
00569     case 366:   
00570     {
00571       
00572       Prefix prefix(msg);
00573       
00574       MessageOut msgout(default_priority(msg.key()));
00575       
00576       boost::shared_ptr<Channel> channel(Target::serverside_get_channel(*this, msg.param(1)));
00577       if (!channel->received_names())
00578       {
00579         
00580         channel->set_received_names();
00581       }
00582       
00583       ASSERT(msg.param(0) == mynick()->in_name(msg.server_session()));
00584       
00585       client_session().queue_msg(msgout << prefix << msg.key() << mynick() << channel << msg.params(2));
00586       break;
00587     }
00588     case 433:   
00589       server_session().nicks().inuse(msg.param(1));
00590       break;
00591     case 451:   
00592       if (server_connection().state() == pong_sent)
00593       {
00594         
00595         
00596         
00597         
00598         
00599         
00600         
00601         
00602         
00603         server_session() << "QUIT\r\n" << std::flush;
00604       }
00605       break;
00606     case QUIT:
00607       do_quit(msg.prefix().get_nick(), msg.param(0));
00608       break;
00609     case NICK:
00610     {
00611       Prefix prefix(msg);
00612       Prefix old_prefix(prefix.out_prefix(client_session()));
00613       boost::shared_ptr<Nick> nick(prefix.get_nick());
00614       nick->serverside_nick_changed_to(msg.server_session(), msg.param(0));     
00615       
00616       nick->clientside_nick_changed_to(client_session(), msg.param(0));         
00617       
00618       MessageOut msgout(default_priority(msg.key()));
00619       client_session().queue_msg(msgout << old_prefix << msg.key() << nick);
00620       break;
00621     }
00622     case NOTICE:                
00623       if (server_connection().state() <= pong_sent)     
00624         break;                  
00625       
00626     case PRIVMSG:               
00627     {
00628       if (msg.params().empty())
00629         break;                  
00630       char c = *msg.params().front().start();
00631       if (c != '#' && c != '&' && c != '@')
00632       {
00633         
00634         
00635         ASSERT(c == '$' || msg.param(0) == server_session().nicks().in_nick() || (msg.key() == NOTICE && msg.param(0) == "*"));
00636         
00637         
00638         Prefix prefix(msg);
00639         MessageOut msgout(default_priority(msg.key()));
00640         if (c == '$' || msg.param(0) == "*")
00641           client_session().queue_msg(msgout << prefix << msg.key() << msg.params(0));
00642         else
00643           client_session().queue_msg(msgout << prefix << msg.key() << mynick() << msg.params(1));
00644         break;
00645       } 
00646       
00647     }
00648     case MODE:                  
00649     case PART:                  
00650     case KICK:                  
00651     case TOPIC:                 
00652     {
00653       
00654       
00655       
00656       Target::serverside_get_channel(*this, msg.param(0), msg.key() == JOIN)->new_server_message_received(msg);
00657       break;
00658     }
00659     case JOIN:                  
00660     {
00661       Target::serverside_get_channel(*this, msg.param(0), msg.key() == JOIN)->new_server_message_received(msg);
00662       break;
00663     }
00664     default:
00665       Dout(dc::warning, "Unhandled command " << msg << " from server");
00666       pass_as_is_to_client(msg);
00667       break;
00668   }
00669 }
00670 
00671 
00672 void Identity::received_network_domain_answer(UserAnswerEventType const& event_type,
00673     std::pair<std::string, std::string> network_domain)
00674 {
00675   DoutEntering(dc::debug, "Identity::received_network_domain_answer(" << event_type);
00676   std::string answer = event_type.answer();
00677   bool yes = IRCStringCompare(answer, "Yes") == 0;
00678   bool no = IRCStringCompare(answer, "No") == 0;
00679   if (!yes && !no)
00680   {
00681     std::ostringstream the_question;
00682     the_question << "Does the " << network_domain.first << " IRC network use \"" <<
00683         network_domain.second << "\" as common domain for all servers (type: Yes|No)?";
00684     client_session().user_answer_event_server
00685         (UserAnswerRequestData(client_session(), network_domain_question, the_question.str()),
00686         *this, &Identity::received_network_domain_answer, network_domain);
00687   }
00688   else if (no)
00689     server_session().construct_network_object(network_domain.first, "");
00690   else
00691     server_session().construct_network_object(network_domain.first, network_domain.second);
00692 }
00693 
00694 #if 0
00695 
00696 std::string Identity::unique_target(char const* prefix) const
00697 {
00698   std::stringstream result;
00699   result << prefix;
00700   ClientSession::private_targets_type::const_iterator iter = client_session().private_targets().find(result.str());
00701   int postfix = 0;
00702   size_t len = strlen(prefix);
00703   while (iter != client_session().private_targets().end())
00704   {
00705     result.rdbuf()->pubseekpos(len);
00706     result << '.' << ++postfix;
00707     iter = client_session().private_targets().find(result.str());
00708   }
00709   return result.str();
00710 }
00711 #endif
00712 
00713 boost::shared_ptr<Target> Identity::notice_target(question_nt number)
00714 {
00715   char const* channel_name;
00716 
00717   if (number != no_related_question)
00718   {
00719     channel_name = question_target_name(number);
00720     ASSERT(is_channel(channel_name));
00721   }
00722 
00723   while(1)
00724   {
00725     if (number == no_related_question)
00726       channel_name = "¬ices";
00727     
00728     ClientSession::private_targets_type::iterator iter = client_session().private_targets().find(channel_name);
00729     if (iter != client_session().private_targets().end())
00730       return iter->second;
00731     if (number == no_related_question)
00732       break;
00733     number = no_related_question;
00734   }
00735 
00736   
00737   NoticeTarget* new_notice_target = new NoticeTarget(client_session(), channel_name, M_private_network);
00738   AllocTag(new_notice_target, channel_name);
00739   
00740   boost::shared_ptr<Target> private_target(new_notice_target);
00741   client_session().add_private_target(private_target);
00742   
00743   client_session() << ":" << client_session().client_out_nick() << " JOIN " << channel_name << "\r\n";
00744   new_notice_target->do_names_output();
00745 
00746   return private_target;
00747 }
00748 
00749 
00750 
00751 
00752 
00753 void Identity::send_notice(std::string const& notice, question_nt number)
00754 {
00755   *M_client_session << ":Leandro PRIVMSG " << notice_target(number)->out_name(*M_client_session)  << " :" << notice << "\r\n";
00756 }
00757 
00758 
00759 std::string Identity::server_source(void) const
00760 {
00761   std::string result;
00762   if (M_primary_server_connection->has_server())
00763     result = M_primary_server_connection->server()->get_irc_name();
00764   if (result.empty())
00765     result = "ircproxy.net";
00766   return result;
00767 }
00768 
00769 
00770 void Identity::serialize(PersistXML& xml)
00771 {
00772   xml.serialize("M_key", M_key);
00773   xml.serialize("M_authpass", M_authpass);
00774   xml.serialize("M_network_name", M_network_name);
00775 }
00776 
00777 Identity::~Identity()
00778 {
00779   Dout(dc::objects, "Destructing Identity " << *this << ".");
00780   
00781   if (has_client_session())
00782     client_session().joined_channels().clear();
00783   if (has_server_session())
00784     server_session().joined_channels().clear();
00785   cancel_all_requests();
00786 }
00787