00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #ifndef _OBBY_CLIENT_BUFFER_HPP_
00020 #define _OBBY_CLIENT_BUFFER_HPP_
00021
00022 #include <net6/default_accumulator.hpp>
00023 #include <net6/client.hpp>
00024 #include "error.hpp"
00025 #include "command.hpp"
00026 #include "local_buffer.hpp"
00027 #include "client_document_info.hpp"
00028
00029 namespace obby
00030 {
00031
00034 template<typename Document, typename Selector>
00035 class basic_client_buffer:
00036 virtual public basic_local_buffer<Document, Selector>
00037 {
00038 public:
00039 struct connection_settings {
00040 std::string name;
00041 obby::colour colour;
00042 std::string global_password;
00043 std::string user_password;
00044 };
00045
00046
00047 typedef typename basic_local_buffer<Document, Selector>::
00048 base_document_info_type base_document_info_type;
00049
00050 typedef basic_client_document_info<Document, Selector>
00051 document_info_type;
00052
00053
00054 typedef typename basic_local_buffer<Document, Selector>::
00055 base_net_type base_net_type;
00056
00057 typedef net6::basic_client<Selector> net_type;
00058
00059
00060 typedef net6::default_accumulator<bool, false> login_accumulator;
00061
00062 typedef sigc::signal<void>
00063 signal_welcome_type;
00064 typedef sigc::signal<void, login::error>
00065 signal_login_failed_type;
00066 typedef sigc::signal<void>
00067 signal_close_type;
00068
00069 typedef typename sigc::signal<bool, connection_settings&>
00070 ::template accumulated<login_accumulator>
00071 signal_prompt_name_type;
00072 typedef typename sigc::signal<bool, connection_settings&>
00073 ::template accumulated<login_accumulator>
00074 signal_prompt_colour_type;
00075 typedef typename sigc::signal<bool, connection_settings&>
00076 ::template accumulated<login_accumulator>
00077 signal_prompt_global_password_type;
00078 typedef typename sigc::signal<bool, connection_settings&>
00079 ::template accumulated<login_accumulator>
00080 signal_prompt_user_password_type;
00081
00084 basic_client_buffer();
00085
00098 void connect(const std::string& hostname, unsigned int port = 6522);
00099
00105 void disconnect();
00106
00109
00110
00113
00114
00126 void login(const std::string& name,
00127 const obby::colour& colour);
00128
00131 bool is_logged_in() const;
00132
00137 virtual void document_create(const std::string& title,
00138 const std::string& encoding,
00139 const std::string& content = "");
00140
00145 virtual void document_remove(base_document_info_type& doc);
00146
00152 document_info_type* document_find(unsigned int owner_id,
00153 unsigned int id) const;
00154
00157 virtual const user& get_self() const;
00158
00162 virtual const std::string& get_name() const;
00163
00166 virtual void send_message(const std::string& message);
00167
00170 virtual void send_command(const command_query& query);
00171
00174 virtual void set_password(const std::string& password);
00175
00178 virtual void set_colour(const colour& colour);
00179
00186 void set_enable_keepalives(bool enable);
00187
00193 signal_welcome_type welcome_event() const;
00194
00198 signal_close_type close_event() const;
00199
00202 signal_login_failed_type login_failed_event() const;
00203
00206 signal_prompt_name_type prompt_name_event() const;
00207
00210 signal_prompt_colour_type prompt_colour_event() const;
00211
00214 signal_prompt_global_password_type prompt_global_password_event() const;
00215
00218 signal_prompt_user_password_type prompt_user_password_event() const;
00219
00220 protected:
00224 void register_signal_handlers();
00225
00228 virtual base_document_info_type*
00229 new_document_info(const user* owner,
00230 unsigned int id,
00231 const std::string& title,
00232 unsigned int suffix,
00233 const std::string& encoding);
00234
00237 virtual base_document_info_type*
00238 new_document_info(const user* owner,
00239 unsigned int id,
00240 const std::string& title,
00241 const std::string& encoding,
00242 const std::string& content);
00243
00246 virtual base_document_info_type*
00247 new_document_info(const net6::packet& pack);
00248
00254 virtual base_net_type* new_net();
00255
00258 void on_join(const net6::user& user6, const net6::packet& pack);
00259 void on_part(const net6::user& user6, const net6::packet& pack);
00260 void on_close();
00261 void on_encrypted();
00262 void on_data(const net6::packet& pack);
00263 void on_login_failed(net6::login::error error);
00264 void on_login_extend(net6::packet& pack);
00265
00268 virtual bool execute_packet(const net6::packet& pack);
00269
00272 virtual void on_net_welcome(const net6::packet& pack);
00273
00276 virtual void on_net_document_create(const net6::packet& pack);
00277 virtual void on_net_document_remove(const net6::packet& pack);
00278
00281 virtual void on_net_message(const net6::packet& pack);
00282 virtual void on_net_emote_message(const net6::packet& pack);
00283
00286 virtual void on_net_user_colour(const net6::packet& pack);
00287 virtual void on_net_user_colour_failed(const net6::packet& pack);
00288
00291 virtual void on_net_sync_init(const net6::packet& pack);
00292 virtual void on_net_sync_usertable_user(const net6::packet& pack);
00293 virtual void on_net_sync_doclist_document(const net6::packet& pack);
00294 virtual void on_net_sync_final(const net6::packet& pack);
00295
00298 virtual void on_net_document(const net6::packet& pack);
00299
00302 virtual void on_net_command_result(const net6::packet& pack);
00303
00304 void on_command_emote(const command_query& query,
00305 const command_result& result);
00306
00309 virtual void session_close();
00310
00314 void session_close_impl();
00315
00316 const user* m_self;
00317
00318 connection_settings m_settings;
00319 bool m_enable_keepalives;
00320
00321 signal_welcome_type m_signal_welcome;
00322 signal_close_type m_signal_close;
00323 signal_login_failed_type m_signal_login_failed;
00324
00325 signal_prompt_name_type m_signal_prompt_name;
00326 signal_prompt_colour_type m_signal_prompt_colour;
00327 signal_prompt_global_password_type m_signal_prompt_global_password;
00328 signal_prompt_user_password_type m_signal_prompt_user_password;
00329 private:
00333 net_type& net6_client();
00334
00338 const net_type& net6_client() const;
00339 };
00340
00341 typedef basic_client_buffer<obby::document, net6::selector> client_buffer;
00342
00343 template<typename Document, typename Selector>
00344 basic_client_buffer<Document, Selector>::basic_client_buffer():
00345 basic_local_buffer<Document, Selector>(), m_self(NULL),
00346 m_enable_keepalives(false)
00347 {
00348 const command_queue& queue =
00349 basic_local_buffer<Document, Selector>::m_command_queue;
00350
00351 queue.result_event("me").connect(
00352 sigc::mem_fun(*this, &basic_client_buffer::on_command_emote)
00353 );
00354 }
00355
00356 template<typename Document, typename Selector>
00357 void basic_client_buffer<Document, Selector>::
00358 connect(const std::string& hostname,
00359 unsigned int port)
00360 {
00361 if(basic_buffer<Document, Selector>::is_open() )
00362 {
00363 throw std::logic_error(
00364 "obby::basic_client_buffer::connect:\n"
00365 "Connection already established"
00366 );
00367 }
00368
00369
00370 basic_buffer<Document, Selector>::m_net.reset(new_net() );
00371
00372
00373 register_signal_handlers();
00374
00375
00376
00377
00378
00379
00380 try
00381 {
00382 net6_client().connect(
00383 net6::ipv4_address::create_from_hostname(
00384 hostname,
00385 port
00386 )
00387 );
00388 }
00389 catch(net6::error& e)
00390 {
00391 if(!IPV6_ENABLED) throw e;
00392
00393 net6_client().connect(
00394 net6::ipv6_address::create_from_hostname(
00395 hostname,
00396 port
00397 )
00398 );
00399 }
00400
00401 net6_client().set_enable_keepalives(m_enable_keepalives);
00402 }
00403
00404 template<typename Document, typename Selector>
00405 void basic_client_buffer<Document, Selector>::disconnect()
00406 {
00407 if(!basic_buffer<Document, Selector>::is_open() )
00408 {
00409 throw std::logic_error(
00410 "obby::basic_client_buffer::disconnect:\n"
00411 "Client is not connected"
00412 );
00413 }
00414
00415
00416 session_close();
00417 }
00418
00419 template<typename Document, typename Selector>
00420 void basic_client_buffer<Document, Selector>::login(const std::string& name,
00421 const colour& colour)
00422 {
00423 m_settings.name = name;
00424 m_settings.colour = colour;
00425
00426 net6_client().login(name);
00427 }
00428
00429 template<typename Document, typename Selector>
00430 bool basic_client_buffer<Document, Selector>::is_logged_in() const
00431 {
00432
00433
00434
00435
00436
00437 if(basic_buffer<Document, Selector>::m_net.get() == NULL) return false;
00438 return net6_client().is_logged_in();
00439 }
00440
00441 template<typename Document, typename Selector>
00442 void basic_client_buffer<Document, Selector>::
00443 document_create(const std::string& title,
00444 const std::string& encoding,
00445 const std::string& content)
00446 {
00447
00448 if(!is_logged_in() )
00449 {
00450 throw std::logic_error(
00451 "obby::basic_client_buffer::document_create:\n"
00452 "Cannot create document without being logged in"
00453 );
00454 }
00455
00456
00457 unsigned int id = ++ basic_buffer<Document, Selector>::m_doc_counter;
00458
00459 base_document_info_type* info =
00460 new_document_info(m_self, id, title, encoding, content);
00461
00462 basic_buffer<Document, Selector>::document_add(*info);
00463
00464 net6::packet request_pack("obby_document_create");
00465 request_pack << id << title << encoding << content;
00466 net6_client().send(request_pack);
00467 }
00468
00469 template<typename Document, typename Selector>
00470 void basic_client_buffer<Document, Selector>::
00471 document_remove(base_document_info_type& document)
00472 {
00473 if(is_logged_in() )
00474 {
00475
00476
00477 net6::packet request_pack("obby_document_remove");
00478 request_pack << &document;
00479 net6_client().send(request_pack);
00480 }
00481 else
00482 {
00483
00484 basic_buffer<Document, Selector>::document_delete(document);
00485 }
00486 }
00487
00488 template<typename Document, typename Selector>
00489 typename basic_client_buffer<Document, Selector>::document_info_type*
00490 basic_client_buffer<Document, Selector>::
00491 document_find(unsigned int owner_id,
00492 unsigned int id) const
00493 {
00494 return dynamic_cast<document_info_type*>(
00495 basic_buffer<Document, Selector>::document_find(owner_id, id)
00496 );
00497 }
00498
00499 template<typename Document, typename Selector>
00500 const obby::user& basic_client_buffer<Document, Selector>::get_self() const
00501 {
00502 if(m_self == NULL)
00503 {
00504 throw std::logic_error(
00505 "obby::basic_client_buffer::get_self:\n"
00506 "Client is not logged in"
00507 );
00508 }
00509
00510 return *m_self;
00511 }
00512
00513 template<typename Document, typename Selector>
00514 const std::string& basic_client_buffer<Document, Selector>::get_name() const
00515 {
00516
00517 if(m_self == NULL) return m_settings.name;
00518 return basic_local_buffer<Document, Selector>::get_name();
00519 }
00520
00521 template<typename Document, typename Selector>
00522 void basic_client_buffer<Document, Selector>::
00523 send_message(const std::string& message)
00524 {
00525 if(is_logged_in() )
00526 {
00527
00528 net6::packet message_pack("obby_message");
00529 message_pack << message;
00530 net6_client().send(message_pack);
00531 }
00532 else
00533 {
00534
00535
00536 if(m_self == NULL)
00537 {
00538 throw std::logic_error(
00539 "obby::basic_client_buffer::send_message:\n"
00540 "No self user available. Probably the client "
00541 "buffer never has been connected to a session."
00542 );
00543 }
00544
00545 basic_buffer<Document, Selector>::m_chat.add_user_message(
00546 message, get_self()
00547 );
00548 }
00549 }
00550
00551 template<typename Document, typename Selector>
00552 void basic_client_buffer<Document, Selector>::
00553 send_command(const command_query& query)
00554 {
00555 if(!is_logged_in() )
00556 {
00557 throw std::logic_error(
00558 "obby::basic_client_buffer::send_command:\n"
00559 "Cannot send command without being logged in"
00560 );
00561 }
00562
00563 basic_local_buffer<Document, Selector>::m_command_queue.query(query);
00564
00565 net6::packet pack("obby_command_query");
00566 query.append_packet(pack);
00567
00568 net6_client().send(pack);
00569 }
00570
00571 template<typename Document, typename Selector>
00572 void basic_client_buffer<Document, Selector>::
00573 set_password(const std::string& password)
00574 {
00575 if(is_logged_in() )
00576 {
00577 net6::packet password_pack("obby_user_password");
00578 password_pack << password;
00579 net6_client().send(password_pack);
00580 }
00581 else
00582 {
00583 throw std::logic_error(
00584 "obby::basic_client_buffer::set_password:\n"
00585 "Cannot set password without being logged in"
00586 );
00587 }
00588 }
00589
00590 template<typename Document, typename Selector>
00591 void basic_client_buffer<Document, Selector>::set_colour(const colour& colour)
00592 {
00593 if(is_logged_in() )
00594 {
00595 net6::packet colour_pack("obby_user_colour");
00596 colour_pack << colour;
00597 net6_client().send(colour_pack);
00598 }
00599 else
00600 {
00601 throw std::logic_error(
00602 "obby::basic_client_buffer::::set_colour:\n"
00603 "Cannot change colour without being logged in"
00604 );
00605 }
00606 }
00607
00608 template<typename Document, typename Selector>
00609 void basic_client_buffer<Document, Selector>::set_enable_keepalives(bool enable)
00610 {
00611 if(m_enable_keepalives == enable) return;
00612
00613 m_enable_keepalives = enable;
00614 if(basic_buffer<Document, Selector>::m_net.get() != NULL)
00615 net6_client().set_enable_keepalives(enable);
00616 }
00617
00618 template<typename Document, typename Selector>
00619 typename basic_client_buffer<Document, Selector>::signal_welcome_type
00620 basic_client_buffer<Document, Selector>::welcome_event() const
00621 {
00622 return m_signal_welcome;
00623 }
00624
00625 template<typename Document, typename Selector>
00626 typename basic_client_buffer<Document, Selector>::signal_login_failed_type
00627 basic_client_buffer<Document, Selector>::login_failed_event() const
00628 {
00629 return m_signal_login_failed;
00630 }
00631
00632 template<typename Document, typename Selector>
00633 typename basic_client_buffer<Document, Selector>::signal_prompt_name_type
00634 basic_client_buffer<Document, Selector>::prompt_name_event() const
00635 {
00636 return m_signal_prompt_name;
00637 }
00638
00639 template<typename Document, typename Selector>
00640 typename basic_client_buffer<Document, Selector>::signal_prompt_colour_type
00641 basic_client_buffer<Document, Selector>::prompt_colour_event() const
00642 {
00643 return m_signal_prompt_colour;
00644 }
00645
00646 template<typename Document, typename Selector>
00647 typename basic_client_buffer<Document, Selector>::
00648 signal_prompt_global_password_type
00649 basic_client_buffer<Document, Selector>::prompt_global_password_event() const
00650 {
00651 return m_signal_prompt_global_password;
00652 }
00653
00654 template<typename Document, typename Selector>
00655 typename basic_client_buffer<Document, Selector>::
00656 signal_prompt_user_password_type
00657 basic_client_buffer<Document, Selector>::prompt_user_password_event() const
00658 {
00659 return m_signal_prompt_user_password;
00660 }
00661
00662 template<typename Document, typename Selector>
00663 typename basic_client_buffer<Document, Selector>::signal_close_type
00664 basic_client_buffer<Document, Selector>::close_event() const
00665 {
00666 return m_signal_close;
00667 }
00668
00669 template<typename Document, typename Selector>
00670 void basic_client_buffer<Document, Selector>::on_join(const net6::user& user6,
00671 const net6::packet& pack)
00672 {
00673 unsigned int id =
00674 pack.get_param(3).net6::parameter::as<unsigned int>();
00675 colour colour =
00676 pack.get_param(4).net6::parameter::as<obby::colour>();
00677
00678
00679 const user* new_user = basic_buffer<Document, Selector>::
00680 m_user_table.add_user(id, user6, colour);
00681
00682
00683 if(m_self == NULL) m_self = new_user;
00684
00685 basic_buffer<Document, Selector>::user_join(*new_user);
00686 }
00687
00688 template<typename Document, typename Selector>
00689 void basic_client_buffer<Document, Selector>::on_part(const net6::user& user6,
00690 const net6::packet& pack)
00691 {
00692
00693 const user* cur_user =
00694 basic_buffer<Document, Selector>::m_user_table.find(
00695 user6,
00696 user::flags::CONNECTED,
00697 user::flags::NONE
00698 );
00699
00700
00701 if(cur_user == NULL)
00702 {
00703 format_string str("User %0% is not connected");
00704 str << user6.get_id();
00705 throw net6::bad_value(str.str() );
00706 }
00707
00708 basic_buffer<Document, Selector>::user_part(*cur_user);
00709 }
00710
00711 template<typename Document, typename Selector>
00712 void basic_client_buffer<Document, Selector>::on_close()
00713 {
00714
00715 disconnect();
00716
00717 m_signal_close.emit();
00718 }
00719
00720 template<typename Document, typename Selector>
00721 void basic_client_buffer<Document, Selector>::on_encrypted()
00722 {
00723
00724 m_signal_welcome.emit();
00725 }
00726
00727 template<typename Document, typename Selector>
00728 void basic_client_buffer<Document, Selector>::on_data(const net6::packet& pack)
00729 {
00730 if(!execute_packet(pack) )
00731 {
00732 throw net6::bad_value(
00733 "Unexpected command: " + pack.get_command()
00734 );
00735 }
00736 }
00737
00738 template<typename Document, typename Selector>
00739 void basic_client_buffer<Document, Selector>::
00740 on_login_failed(net6::login::error error)
00741 {
00742 if(error == net6::login::ERROR_NAME_IN_USE)
00743 {
00744 if(m_signal_prompt_name.emit(m_settings) )
00745 login(m_settings.name, m_settings.colour);
00746 }
00747 else if(error == login::ERROR_COLOUR_IN_USE)
00748 {
00749 if(m_signal_prompt_colour.emit(m_settings) )
00750 login(m_settings.name, m_settings.colour);
00751 }
00752 else if(error == login::ERROR_WRONG_GLOBAL_PASSWORD)
00753 {
00754 if(m_signal_prompt_global_password.emit(m_settings) )
00755 login(m_settings.name, m_settings.colour);
00756 }
00757 else if(error == login::ERROR_WRONG_USER_PASSWORD)
00758 {
00759 if(m_signal_prompt_user_password.emit(m_settings) )
00760 login(m_settings.name, m_settings.colour);
00761 }
00762 else
00763 {
00764 m_signal_login_failed.emit(error);
00765 }
00766 }
00767
00768 template<typename Document, typename Selector>
00769 void basic_client_buffer<Document, Selector>::
00770 on_login_extend(net6::packet& pack)
00771 {
00772
00773 pack << m_settings.colour;
00774 if(!m_settings.global_password.empty() ||
00775 !m_settings.user_password.empty() )
00776 {
00777 pack << m_settings.global_password;
00778 if(!m_settings.user_password.empty() )
00779 pack << m_settings.user_password;
00780 }
00781 }
00782
00783 template<typename Document, typename Selector>
00784 bool basic_client_buffer<Document, Selector>::
00785 execute_packet(const net6::packet& pack)
00786 {
00787
00788 if(pack.get_command() == "obby_welcome")
00789 { on_net_welcome(pack); return true; }
00790
00791 if(pack.get_command() == "obby_document_create")
00792 { on_net_document_create(pack); return true; }
00793
00794 if(pack.get_command() == "obby_document_remove")
00795 { on_net_document_remove(pack); return true; }
00796
00797 if(pack.get_command() == "obby_message")
00798 { on_net_message(pack); return true; }
00799
00800 if(pack.get_command() == "obby_emote_message")
00801 { on_net_emote_message(pack); return true; }
00802
00803 if(pack.get_command() == "obby_user_colour")
00804 { on_net_user_colour(pack); return true; }
00805
00806 if(pack.get_command() == "obby_user_colour_failed")
00807 { on_net_user_colour_failed(pack); return true; }
00808
00809 if(pack.get_command() == "obby_sync_init")
00810 { on_net_sync_init(pack); return true; }
00811
00812 if(pack.get_command() == "obby_sync_usertable_user")
00813 { on_net_sync_usertable_user(pack); return true; }
00814
00815 if(pack.get_command() == "obby_sync_doclist_document")
00816 { on_net_sync_doclist_document(pack); return true; }
00817
00818 if(pack.get_command() == "obby_sync_final")
00819 { on_net_sync_final(pack); return true; }
00820
00821 if(pack.get_command() == "obby_document")
00822 { on_net_document(pack); return true; }
00823
00824 if(pack.get_command() == "obby_command_result")
00825 { on_net_command_result(pack); return true; }
00826
00827 return false;
00828 }
00829
00830 template<typename Document, typename Selector>
00831 void basic_client_buffer<Document, Selector>::
00832 on_net_welcome(const net6::packet& pack)
00833 {
00834
00835
00836 unsigned long server_version =
00837 pack.get_param(0).net6::parameter::as<unsigned long>();
00838
00839 if(server_version != PROTOCOL_VERSION)
00840 {
00841 on_login_failed(login::ERROR_PROTOCOL_VERSION_MISMATCH);
00842 return;
00843 }
00844
00845
00846
00847
00848
00849
00850
00851
00852 }
00853
00854 template<typename Document, typename Selector>
00855 void basic_client_buffer<Document, Selector>::
00856 on_net_document_create(const net6::packet& pack)
00857 {
00858
00859 const user* owner = pack.get_param(0).net6::parameter::as<const user*>(
00860 ::serialise::hex_context_from<const user*>(
00861 basic_buffer<Document, Selector>::get_user_table()
00862 )
00863 );
00864
00865 unsigned int id =
00866 pack.get_param(1).net6::parameter::as<unsigned int>();
00867 const std::string& title =
00868 pack.get_param(2).net6::parameter::as<std::string>();
00869 unsigned int suffix =
00870 pack.get_param(3).net6::parameter::as<unsigned int>();
00871 const std::string& encoding =
00872 pack.get_param(4).net6::parameter::as<std::string>();
00873
00874
00875 unsigned int owner_id = (owner == NULL ? 0 : owner->get_id() );
00876
00877
00878
00879 if(owner == m_self)
00880 {
00881 format_string str("Owner of document %0%/%1% is self");
00882 str << owner_id << id;
00883 throw net6::bad_value(str.str() );
00884 }
00885
00886
00887 if(document_find(owner_id, id) )
00888 {
00889 format_string str("Document %0%/%1% exists already");
00890 str << owner_id << id;
00891 throw net6::bad_value(str.str() );
00892 }
00893
00894
00895 base_document_info_type* info =
00896 new_document_info(owner, id, title, suffix, encoding);
00897
00898 basic_buffer<Document, Selector>::document_add(*info);
00899 }
00900
00901 template<typename Document, typename Selector>
00902 void basic_client_buffer<Document, Selector>::
00903 on_net_document_remove(const net6::packet& pack)
00904 {
00905
00906 document_info_type& doc = dynamic_cast<document_info_type&>(
00907 *pack.get_param(0).net6::parameter::as<
00908 base_document_info_type*
00909 >(::serialise::hex_context_from<base_document_info_type*>(
00910 *this
00911 ))
00912 );
00913
00914
00915
00916 for(typename document_info_type::user_iterator user_iter =
00917 doc.user_begin();
00918 user_iter != doc.user_end();
00919 ++ user_iter)
00920 {
00921 doc.unsubscribe_event().emit(*user_iter);
00922 }
00923
00924
00925 basic_buffer<Document, Selector>::document_delete(doc);
00926 }
00927
00928 template<typename Document, typename Selector>
00929 void basic_client_buffer<Document, Selector>::
00930 on_net_message(const net6::packet& pack)
00931 {
00932 const user* writer = pack.get_param(0).net6::parameter::as<const user*>(
00933 ::serialise::hex_context_from<const user*>(
00934 basic_buffer<Document, Selector>::get_user_table()
00935 )
00936 );
00937
00938 const std::string& message =
00939 pack.get_param(1).net6::parameter::as<std::string>();
00940
00941
00942
00943 if(writer != NULL)
00944 {
00945 basic_buffer<Document, Selector>::m_chat.add_user_message(
00946 message,
00947 *writer
00948 );
00949 }
00950 else
00951 {
00952 basic_buffer<Document, Selector>::m_chat.add_server_message(
00953 message
00954 );
00955 }
00956 }
00957
00958 template<typename Document, typename Selector>
00959 void basic_client_buffer<Document, Selector>::
00960 on_net_emote_message(const net6::packet& pack)
00961 {
00962 const user* writer = pack.get_param(0).net6::parameter::as<const user*>(
00963 ::serialise::hex_context_from<const user*>(
00964 basic_buffer<Document, Selector>::get_user_table()
00965 )
00966 );
00967
00968 const std::string& message =
00969 pack.get_param(1).net6::parameter::as<std::string>();
00970
00971 if(writer == NULL)
00972 {
00973 throw std::logic_error(
00974 "obby::basic_client_buffer::on_net_emote_message:\n"
00975 "Server cannot send emote messages"
00976 );
00977 }
00978
00979 basic_buffer<Document, Selector>::m_chat.add_emote_message(
00980 message,
00981 *writer
00982 );
00983 }
00984
00985 template<typename Document, typename Selector>
00986 void basic_client_buffer<Document, Selector>::
00987 on_net_user_colour(const net6::packet& pack)
00988 {
00989 const user* from = pack.get_param(0).net6::parameter::as<const user*>(
00990 ::serialise::hex_context_from<const user*>(
00991 basic_buffer<Document, Selector>::get_user_table()
00992 )
00993 );
00994
00995 basic_buffer<Document, Selector>::m_user_table.set_user_colour(
00996 *from,
00997 pack.get_param(1).net6::parameter::as<obby::colour>()
00998 );
00999
01000
01001 basic_buffer<Document, Selector>::m_signal_user_colour.emit(*from);
01002 }
01003
01004 template<typename Document, typename Selector>
01005 void basic_client_buffer<Document, Selector>::
01006 on_net_user_colour_failed(const net6::packet& pack)
01007 {
01008 basic_local_buffer<Document, Selector>::
01009 m_signal_user_colour_failed.emit();
01010 }
01011
01012 template<typename Document, typename Selector>
01013 void basic_client_buffer<Document, Selector>::
01014 on_net_sync_init(const net6::packet& pack)
01015 {
01016
01017
01018
01019 basic_buffer<Document, Selector>::m_user_table.clear();
01020 basic_buffer<Document, Selector>::document_clear();
01021 m_self = NULL;
01022
01023 basic_buffer<Document, Selector>::m_signal_sync_init.emit(
01024 pack.get_param(0).net6::parameter::as<unsigned int>()
01025 );
01026 }
01027
01028 template<typename Document, typename Selector>
01029 void basic_client_buffer<Document, Selector>::
01030 on_net_sync_usertable_user(const net6::packet& pack)
01031 {
01032
01033
01034
01035 unsigned int id =
01036 pack.get_param(0).net6::parameter::as<unsigned int>();
01037 const std::string& name =
01038 pack.get_param(1).net6::parameter::as<std::string>();
01039 colour colour =
01040 pack.get_param(2).net6::parameter::as<obby::colour>();
01041
01042
01043 basic_buffer<Document, Selector>::m_user_table.add_user(
01044 id, name, colour
01045 );
01046
01047
01048
01049 }
01050
01051 template<typename Document, typename Selector>
01052 void basic_client_buffer<Document, Selector>::
01053 on_net_sync_doclist_document(const net6::packet& pack)
01054 {
01055
01056 const user* owner = pack.get_param(0).net6::parameter::as<const user*>(
01057 ::serialise::hex_context_from<const user*>(
01058 basic_buffer<Document, Selector>::get_user_table()
01059 )
01060 );
01061
01062 unsigned int id =
01063 pack.get_param(1).net6::parameter::as<unsigned int>();
01064
01065
01066 unsigned int owner_id = (owner == NULL ? 0 : owner->get_id() );
01067
01068
01069
01070 if(owner_id == m_self->get_id() &&
01071 id >= basic_buffer<Document, Selector>::m_doc_counter)
01072 {
01073 basic_buffer<Document, Selector>::m_doc_counter = id + 1;
01074 }
01075
01076
01077 if(document_find(owner_id, id) != NULL)
01078 {
01079 format_string str("Document %0%/%1% exists already");
01080 str << owner_id << id;
01081 throw net6::bad_value(str.str() );
01082 }
01083
01084
01085 base_document_info_type* info = new_document_info(pack);
01086
01087 basic_buffer<Document, Selector>::document_add(*info);
01088 }
01089
01090 template<typename Document, typename Selector>
01091 void basic_client_buffer<Document, Selector>::
01092 on_net_sync_final(const net6::packet& pack)
01093 {
01094 basic_buffer<Document, Selector>::m_signal_sync_final.emit();
01095 }
01096
01097 template<typename Document, typename Selector>
01098 void basic_client_buffer<Document, Selector>::
01099 on_net_document(const net6::packet& pack)
01100 {
01101
01102 document_info_type& info = dynamic_cast<document_info_type&>(
01103 *pack.get_param(0).net6::parameter::as<
01104 base_document_info_type*
01105 >(::serialise::hex_context_from<base_document_info_type*>(
01106 *this
01107 ))
01108 );
01109
01110
01111
01112 info.on_net_packet(document_packet(pack) );
01113 }
01114
01115 template<typename Document, typename Selector>
01116 void basic_client_buffer<Document, Selector>::
01117 on_net_command_result(const net6::packet& pack)
01118 {
01119 unsigned int index = 0;
01120 command_result result(pack, index);
01121
01122 basic_local_buffer<Document, Selector>::m_command_queue.result(result);
01123 }
01124
01125 template<typename Document, typename Selector>
01126 void basic_client_buffer<Document, Selector>::
01127 on_command_emote(const command_query& query,
01128 const command_result& result)
01129 {
01130 basic_buffer<Document, Selector>::m_chat.add_emote_message(
01131 query.get_paramlist(),
01132 *m_self
01133 );
01134 }
01135
01136 template<typename Document, typename Selector>
01137 void basic_client_buffer<Document, Selector>::session_close()
01138 {
01139 session_close_impl();
01140 basic_local_buffer<Document, Selector>::session_close_impl();
01141 basic_buffer<Document, Selector>::session_close_impl();
01142 }
01143
01144 template<typename Document, typename Selector>
01145 void basic_client_buffer<Document, Selector>::session_close_impl()
01146 {
01147
01148 m_settings.global_password = m_settings.user_password = "";
01149 }
01150
01151 template<typename Document, typename Selector>
01152 void basic_client_buffer<Document, Selector>::register_signal_handlers()
01153 {
01154 net6_client().join_event().connect(
01155 sigc::mem_fun(*this, &basic_client_buffer::on_join) );
01156 net6_client().part_event().connect(
01157 sigc::mem_fun(*this, &basic_client_buffer::on_part) );
01158 net6_client().close_event().connect(
01159 sigc::mem_fun(*this, &basic_client_buffer::on_close) );
01160 net6_client().encrypted_event().connect(
01161 sigc::mem_fun(*this, &basic_client_buffer::on_encrypted) );
01162 net6_client().data_event().connect(
01163 sigc::mem_fun(*this, &basic_client_buffer::on_data) );
01164 net6_client().login_failed_event().connect(
01165 sigc::mem_fun(*this, &basic_client_buffer::on_login_failed) );
01166 net6_client().login_extend_event().connect(
01167 sigc::mem_fun(*this, &basic_client_buffer::on_login_extend) );
01168 }
01169
01170 template<typename Document, typename Selector>
01171 typename basic_client_buffer<Document, Selector>::base_document_info_type*
01172 basic_client_buffer<Document, Selector>::
01173 new_document_info(const user* owner,
01174 unsigned int id,
01175 const std::string& title,
01176 unsigned int suffix,
01177 const std::string& encoding)
01178 {
01179
01180 return new document_info_type(
01181 *this, net6_client(), owner, id, title, suffix, encoding
01182 );
01183 }
01184
01185 template<typename Document, typename Selector>
01186 typename basic_client_buffer<Document, Selector>::base_document_info_type*
01187 basic_client_buffer<Document, Selector>::
01188 new_document_info(const user* owner,
01189 unsigned int id,
01190 const std::string& title,
01191 const std::string& encoding,
01192 const std::string& content)
01193 {
01194 return new document_info_type(
01195 *this, net6_client(), owner, id, title, encoding, content
01196 );
01197 }
01198
01199 template<typename Document, typename Selector>
01200 typename basic_client_buffer<Document, Selector>::base_document_info_type*
01201 basic_client_buffer<Document, Selector>::
01202 new_document_info(const net6::packet& pack)
01203 {
01204 return new document_info_type(*this, net6_client(), pack);
01205 }
01206
01207 template<typename Document, typename Selector>
01208 typename basic_client_buffer<Document, Selector>::base_net_type*
01209 basic_client_buffer<Document, Selector>::new_net()
01210 {
01211
01212 return new net_type;
01213 }
01214
01215 template<typename Document, typename Selector>
01216 typename basic_client_buffer<Document, Selector>::net_type&
01217 basic_client_buffer<Document, Selector>::net6_client()
01218 {
01219 return dynamic_cast<net_type&>(
01220 *basic_buffer<Document, Selector>::m_net.get()
01221 );
01222 }
01223
01224 template<typename Document, typename Selector>
01225 const typename basic_client_buffer<Document, Selector>::net_type&
01226 basic_client_buffer<Document, Selector>::net6_client() const
01227 {
01228 return dynamic_cast<const net_type&>(
01229 *basic_buffer<Document, Selector>::m_net.get()
01230 );
01231 }
01232
01233 }
01234
01235 #endif // _OBBY_CLIENT_BUFFER_HPP_