Changeset 5f1602ef2512b6a907744ba59be88e0390453929
- Timestamp:
- 01/06/07 23:49:10 (6 years ago)
- Parents:
- f4fe94fc7580e639bec5d34dcc524a75c7f2105b
- Children:
- 296b5a23bbf9b07a67acba878b659ab0bf800ef4
- git-committer:
- Philipp Kern <phil@0x539.de> / 2007-01-06T22:49:10Z+0000
- Files:
-
- 8 modified
-
inc/hostprogressdialog.hpp (modified) (2 diffs)
-
inc/io/buffer_wrapper.hpp (modified) (4 diffs)
-
inc/joinprogressdialog.hpp (modified) (3 diffs)
-
inc/progressdialog.hpp (modified) (2 diffs)
-
src/hostprogressdialog.cpp (modified) (3 diffs)
-
src/io/buffer_wrapper.cpp (modified) (3 diffs)
-
src/joinprogressdialog.cpp (modified) (3 diffs)
-
src/progressdialog.cpp (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
inc/hostprogressdialog.hpp
r8140232 r5f1602e 34 34 const Glib::ustring& username, 35 35 const Gdk::Color& color); 36 ~HostProgressDialog();37 36 38 37 /** Never call this function twice because the auto_ptr of the … … 43 42 44 43 private: 45 virtual void on_thread( );44 virtual void on_thread(Thread& thread); 46 45 47 46 virtual void on_work(); -
inc/io/buffer_wrapper.hpp
r2fe47ae r5f1602e 45 45 { 46 46 public: 47 /** Creates a new client object. A connection may be established 48 * using the inherited connect() method. 49 */ 50 #ifdef WIN32 51 client(Gtk::Window& window); 52 #else 53 client(); 54 #endif 55 47 56 /** Establishes a new client connection to the given host. 48 57 */ … … 54 63 virtual ~client(); 55 64 65 virtual void connect(const net6::address& addr); 66 virtual void disconnect(); 67 56 68 /** Sends a packet to the server. 57 69 */ … … 61 73 virtual void on_send_event(); 62 74 63 main_connection m_ioconn; 75 std::auto_ptr<main_connection> m_ioconn; 76 #ifdef WIN32 77 Gtk::Window& m_window; 78 #endif 79 private: 80 void connect_impl(const net6::address& addr); 81 void disconnect_impl(); 64 82 }; 65 83 … … 222 240 Gtk::Window& m_window; 223 241 #endif 224 virtual net_type* new_net( const std::string& host, unsigned int port);242 virtual net_type* new_net(); 225 243 }; 226 244 -
inc/joinprogressdialog.hpp
r230eee4 r5f1602e 36 36 const Glib::ustring& username, 37 37 const Gdk::Color& color); 38 ~JoinProgressDialog();39 38 40 39 /** Never call this function twice because the auto_ptr of the … … 45 44 46 45 private: 47 virtual bool on_idle(); 48 49 virtual void on_thread(); 46 virtual void on_thread(Thread& thread); 50 47 virtual void on_done(); 51 48 … … 69 66 Gdk::Color m_color; 70 67 68 Glib::ustring m_error; 69 71 70 std::auto_ptr<obby::client_buffer> m_buffer; 71 72 // Got done signal from connection thread 73 bool m_got_done; 74 // Got welcome packet 75 bool m_got_welcome; 72 76 }; 73 77 -
inc/progressdialog.hpp
r230eee4 r5f1602e 30 30 { 31 31 public: 32 class Thread 33 { 34 public: 35 typedef sigc::slot<void, Thread&> entry_slot; 36 37 Thread(); 38 ~Thread(); 39 40 void launch(const entry_slot& entry_func); 41 42 /** Tells the thread to quit as soon as possible. This happens 43 * if the user closed the dialog without waiting for the data 44 * the thread is computing. This means that the user wants to 45 * abort the operation. 46 */ 47 void quit(); 48 49 /** Returns TRUE if the thread has to quit. This may be used 50 * by the thread's entry point to determinate whether to go on 51 * computing some data or whether to return. 52 */ 53 bool quitting(); 54 55 /** Makes sure that the calling thread is this worker thread. 56 */ 57 void assert_running() const; 58 59 /** Locks the thread's mutex. The thread itself must do this 60 * while requesting any data from the dialog object because the 61 * dialog may get destroyed if the user closes the dialog 62 * while the thread is still working. 63 */ 64 void lock(); 65 66 /** Unlocks the mutex mentioned above. 67 */ 68 void unlock(); 69 70 Glib::Dispatcher& done_event(); 71 Glib::Dispatcher& work_event(); 72 73 protected: 74 Glib::Mutex m_mutex; 75 Glib::Thread* m_thread; 76 entry_slot m_entry_func; 77 Glib::Dispatcher m_disp_done; 78 Glib::Dispatcher m_disp_work; 79 bool m_quit; 80 private: 81 void on_thread_entry(); 82 }; 83 32 84 ProgressDialog(const Glib::ustring& title, Gtk::Window& parent); 33 ~ProgressDialog();85 virtual ~ProgressDialog(); 34 86 35 87 void set_status_text(const Glib::ustring& text); 36 88 void set_progress_fraction(double progress); 37 89 void progress_pulse(); 90 protected: 91 /** Emits the work dispatcher of the thread to tell the main thread 92 * that the thread has not hung up or something. 93 * @param thread Thread whose mutex to lock. We cannot just use 94 * m_thread because the dialog may already be destroyed. 95 */ 96 void work(Thread& thread); 38 97 39 void work(); 40 protected: 41 virtual void on_thread(); 98 /** Locks the thread's mutex (as mentioned above) and throws 99 * Glib::Thread::Exit if the thread's quitting flag has been set. 100 * This causes the worker thread to exit if the dialog has been closed. 101 */ 102 void lock(Thread& thread); 103 104 /** Unlocks the thread's mutex. 105 */ 106 void unlock(Thread& thread); 107 108 virtual void on_thread(Thread& thread) = 0; 42 109 43 110 virtual void on_work(); … … 49 116 Gtk::ProgressBar m_progress; 50 117 51 Glib::Thread* m_thread; 52 53 Glib::Dispatcher m_disp_work; 54 Glib::Dispatcher m_disp_done; 118 Thread* m_thread; 55 119 56 120 Gtk::Window& m_parent; 57 121 58 int m_quit;59 virtual bool on_idle();60 122 private: 61 void thread_entry();123 bool on_idle(); 62 124 }; 63 125 -
src/hostprogressdialog.cpp
r2fe47ae r5f1602e 33 33 } 34 34 35 Gobby::HostProgressDialog::~HostProgressDialog()36 {37 }38 39 35 std::auto_ptr<obby::host_buffer> Gobby::HostProgressDialog::get_buffer() 40 36 { … … 42 38 } 43 39 44 void Gobby::HostProgressDialog::on_thread( )40 void Gobby::HostProgressDialog::on_thread(Thread& thread) 45 41 { 46 // Get color components 42 // Lock the thread while retrieving data from the dialog because the 43 // dialog may no longer exist. 44 lock(thread); 45 46 // Put data that is stored with the dialog onto the stack to be 47 // allowed to use it without having locked the thread. 48 #ifdef WIN32 49 Gtk::Window& parent = m_parent; // Parent window 50 #endif 51 Glib::ustring username = m_username; // Local user name 52 unsigned int port = m_port; // Port to open the server on 53 54 // Local user colour 47 55 unsigned int red = m_color.get_red() * 255 / 65535; 48 56 unsigned int green = m_color.get_green() * 255 / 65535; 49 57 unsigned int blue = m_color.get_blue() * 255 / 65535; 50 58 59 // Dialog may now be closed 60 unlock(thread); 61 62 std::auto_ptr<obby::host_buffer> buffer; // Resulting obby buffer 63 Glib::ustring error; // Error message 64 65 // Try to open the server. 51 66 try 52 67 { 53 // Create buffer 54 m_buffer.reset(68 // Create buffer, compute RSA key and stuff 69 buffer.reset( 55 70 new obby::io::host_buffer( 56 71 #ifdef WIN32 57 m_parent,72 parent, 58 73 #endif 59 m_username, 60 red, green, blue 74 username, red, green, blue 61 75 ) 62 76 ); 63 77 64 //set_status_text("Creating session...");78 work(thread); 65 79 66 m_buffer->open(m_port); 80 // Open the server on the given port 81 buffer->open(port); 67 82 } 68 83 catch(net6::error& e) 69 84 { 70 85 // Store error, if one occured 71 m_error = e.what();86 error = e.what(); 72 87 } 88 89 // Regain lock 90 lock(thread); 91 // Set resulting buffer 92 m_buffer = buffer; 93 // ... and error, if any 94 m_error = error; 95 // Unlock before exiting 96 unlock(thread); 97 98 // Resulting data has been transmitted, thread may exit 73 99 } 74 100 … … 81 107 void Gobby::HostProgressDialog::on_done() 82 108 { 83 // Call base function (which joinsthe thread)109 // Call base function (which removes references to the thread) 84 110 ProgressDialog::on_done(); 85 111 -
src/io/buffer_wrapper.cpp
r2fe47ae r5f1602e 22 22 23 23 #ifdef WIN32 24 obby::io::client::client(Gtk::Window& window) 25 #else 26 obby::io::client::client() 27 #endif 28 : net6::client(), m_ioconn(NULL) 29 #ifdef WIN32 30 , m_window(window) 31 #endif 32 { 33 } 34 35 #ifdef WIN32 24 36 obby::io::client::client(Gtk::Window& window, const net6::address& addr) 25 37 #else 26 38 obby::io::client::client(const net6::address& addr) 27 39 #endif 28 : net6::client(addr), 29 m_ioconn( 30 #ifdef WIN32 31 window, 32 #endif 33 conn->get_socket(), 34 35 main_connection::IO_IN | main_connection::IO_ERROR 36 ) 37 { 40 : net6::client(addr), m_ioconn(NULL) 41 #ifdef WIN32 42 , m_window(window) 43 #endif 44 { 45 connect_impl(addr); 38 46 } 39 47 40 48 obby::io::client::~client() 41 49 { 50 if(is_connected() ) 51 disconnect_impl(); 52 } 53 54 void obby::io::client::connect(const net6::address& addr) 55 { 56 net6::client::connect(addr); 57 connect_impl(addr); 58 } 59 60 void obby::io::client::disconnect() 61 { 62 disconnect_impl(); 63 net6::client::disconnect(); 42 64 } 43 65 44 66 void obby::io::client::send(const net6::packet& pack) 45 67 { 46 m_ioconn .add_events(main_connection::IO_OUT);68 m_ioconn->add_events(main_connection::IO_OUT); 47 69 net6::client::send(pack); 48 70 } … … 50 72 void obby::io::client::on_send_event() 51 73 { 52 m_ioconn .remove_events(main_connection::IO_OUT);74 m_ioconn->remove_events(main_connection::IO_OUT); 53 75 net6::client::on_send_event(); 76 } 77 78 void obby::io::client::connect_impl(const net6::address& addr) 79 { 80 m_ioconn.reset( 81 new main_connection( 82 #ifdef WIN32 83 m_window, 84 #endif 85 conn->get_socket(), 86 main_connection::IO_IN | main_connection::IO_ERROR 87 ) 88 ); 89 } 90 91 void obby::io::client::disconnect_impl() 92 { 93 m_ioconn.reset(NULL); 54 94 } 55 95 … … 275 315 } 276 316 277 obby::io::client_buffer::net_type* 278 obby::io::client_buffer::new_net(const std::string& host, unsigned int port) 279 { 280 net6::ipv4_address addr( 281 net6::ipv4_address::create_from_hostname(host, port) 282 ); 283 284 #ifdef WIN32 285 return new net_type(m_window, addr); 286 #else 287 return new net_type(addr); 317 obby::io::client_buffer::net_type* obby::io::client_buffer::new_net() 318 { 319 #ifdef WIN32 320 return new net_type(m_window); 321 #else 322 return new net_type; 288 323 #endif 289 324 } -
src/joinprogressdialog.cpp
r2fe47ae r5f1602e 31 31 const Gdk::Color& color) 32 32 : ProgressDialog(_("Joining obby session..."), parent), m_config(config), 33 m_hostname(hostname), m_port(port), m_username(username), m_color(color) 33 m_hostname(hostname), m_port(port), m_username(username), m_color(color), 34 m_got_done(false), m_got_welcome(false) 34 35 { 35 36 obby::format_string str("Connecting to %0%..."); 36 37 str << hostname; 37 38 set_status_text(str.str() ); 38 39 m_thread = NULL;40 }41 42 Gobby::JoinProgressDialog::~JoinProgressDialog()43 {44 39 } 45 40 … … 49 44 } 50 45 51 void Gobby::JoinProgressDialog::on_thread() 52 { 53 /*try 54 { 55 m_buffer.reset( 46 void Gobby::JoinProgressDialog::on_thread(Thread& thread) 47 { 48 // Get initial data from dialog 49 lock(thread); 50 51 #ifdef WIN32 52 Gtk::Window& parent = m_parent; 53 #endif 54 // Connection data 55 Glib::ustring hostname = m_hostname; // Remote host name 56 unsigned int port = m_port; // TCP port number 57 58 // Dialog may be closed now 59 unlock(thread); 60 61 std::auto_ptr<obby::client_buffer> buffer; // Resulting buffer 62 Glib::ustring error; // Error message 63 64 // Establish connection 65 try 66 { 67 buffer.reset( 56 68 new obby::io::client_buffer( 57 69 #ifdef WIN32 58 m_parent,70 parent 59 71 #endif 60 m_hostname, 61 m_port 62 ) 63 ); 72 ) 73 ); 74 75 // Install signal handlers (notice that these get called within 76 // the main thread) 77 buffer->welcome_event().connect( 78 sigc::mem_fun(*this, &JoinProgressDialog::on_welcome) ); 79 80 buffer->login_failed_event().connect( 81 sigc::mem_fun( 82 *this, 83 &JoinProgressDialog::on_login_failed 84 ) 85 ); 86 87 buffer->global_password_event().connect( 88 sigc::mem_fun( 89 *this, 90 &JoinProgressDialog::on_global_password 91 ) 92 ); 93 94 buffer->user_password_event().connect( 95 sigc::mem_fun( 96 *this, 97 &JoinProgressDialog::on_user_password 98 ) 99 ); 100 101 buffer->sync_init_event().connect( 102 sigc::mem_fun( 103 *this, 104 &JoinProgressDialog::on_sync_init 105 ) 106 ); 107 108 buffer->sync_final_event().connect( 109 sigc::mem_fun( 110 *this, 111 &JoinProgressDialog::on_sync_final 112 ) 113 ); 114 115 buffer->close_event().connect( 116 sigc::mem_fun(*this, &JoinProgressDialog::on_close) ); 117 118 // Establish connection 119 buffer->connect(hostname, port); 64 120 } 65 121 catch(net6::error& e) 66 122 { 67 m_error = e.what(); 68 }*/ 123 // Store error message, if any 124 error = e.what(); 125 } 126 127 // Regain lock 128 lock(thread); 129 // Set resulting buffer 130 m_buffer = buffer; 131 m_error = error; 132 // Unlock before exiting 133 unlock(thread); 134 135 // Thread may finish now 69 136 } 70 137 71 138 void Gobby::JoinProgressDialog::on_done() 72 139 { 73 // Call base function joining the thread 74 //ProgressDialog::on_done(); 75 76 try 77 { 78 // Create buffer 79 m_buffer.reset( 80 new obby::io::client_buffer( 81 #ifdef WIN32 82 m_parent 83 #endif 84 ) 85 ); 86 87 // Connect to remote host 88 m_buffer->connect(m_hostname, m_port); 89 } 90 catch(net6::error& e) 91 { 92 // Display error 93 display_error(e.what() ); 94 // Return 140 ProgressDialog::on_done(); 141 142 // Did we get an error while connecting? 143 if(!m_error.empty() ) 144 { 145 // Display it 146 display_error(m_error); 147 // Bad response 95 148 response(Gtk::RESPONSE_CANCEL); 96 return; 97 } 98 99 m_buffer->welcome_event().connect( 100 sigc::mem_fun(*this, &JoinProgressDialog::on_welcome) ); 101 m_buffer->login_failed_event().connect( 102 sigc::mem_fun(*this, &JoinProgressDialog::on_login_failed) ); 103 m_buffer->global_password_event().connect( 104 sigc::mem_fun(*this, &JoinProgressDialog::on_global_password) ); 105 m_buffer->user_password_event().connect( 106 sigc::mem_fun(*this, &JoinProgressDialog::on_user_password) ); 107 m_buffer->sync_init_event().connect( 108 sigc::mem_fun(*this, &JoinProgressDialog::on_sync_init) ); 109 m_buffer->sync_final_event().connect( 110 sigc::mem_fun(*this, &JoinProgressDialog::on_sync_final) ); 111 m_buffer->close_event().connect( 112 sigc::mem_fun(*this, &JoinProgressDialog::on_close) ); 113 114 // Wait for welcome packet 149 } 150 151 // Thread has established connection, wait for welcome packet 115 152 set_status_text(_("Waiting for welcome packet...") ); 116 153 set_progress_fraction(1.0/4.0); 154 m_got_done = true; 155 156 // on_welcome may be called before on_done is called if the 157 // server replies faster then the thread dispatches, this happens 158 // especially with connections to localhost. 159 // Recall on_welcome in this case now 160 if(m_got_welcome) 161 on_welcome(); 117 162 } 118 163 119 164 void Gobby::JoinProgressDialog::on_welcome() 120 165 { 166 m_got_welcome = true; 167 168 // Do nothing if we have not already got the done signal from the 169 // thread. 170 if(!m_got_done) 171 return; 172 121 173 // TODO: Show key ID to user and allow him to deny connection 122 174 // Got welcome packet, send login packet now … … 200 252 } 201 253 202 bool Gobby::JoinProgressDialog::on_idle()203 {204 on_done();205 return false;206 }207 -
src/progressdialog.cpp
rab042e6 r5f1602e 17 17 */ 18 18 19 #include <stdexcept> 19 20 #include <gtkmm/stock.h> 20 21 #include <gtkmm/main.h> … … 22 23 #include "progressdialog.hpp" 23 24 25 Gobby::ProgressDialog::Thread::Thread() 26 : m_thread(NULL), m_quit(false) 27 { 28 } 29 30 Gobby::ProgressDialog::Thread::~Thread() 31 { 32 } 33 34 void Gobby::ProgressDialog::Thread::launch(const entry_slot& entry_func) 35 { 36 // TODO: sigc::bind to on_thread_entry 37 m_entry_func = entry_func; 38 m_thread = Glib::Thread::create( 39 sigc::mem_fun(*this, &Thread::on_thread_entry), 40 false 41 ); 42 } 43 44 void Gobby::ProgressDialog::Thread::quit() 45 { 46 lock(); 47 m_quit = true; 48 unlock(); 49 } 50 51 bool Gobby::ProgressDialog::Thread::quitting() 52 { 53 return m_quit; 54 } 55 56 void Gobby::ProgressDialog::Thread::assert_running() const 57 { 58 if(Glib::Thread::self() != m_thread) 59 { 60 throw std::logic_error( 61 "Gobby::ProgressDialog::Thread::assert_running" 62 ); 63 } 64 } 65 66 void Gobby::ProgressDialog::Thread::lock() 67 { 68 m_mutex.lock(); 69 } 70 71 void Gobby::ProgressDialog::Thread::unlock() 72 { 73 m_mutex.unlock(); 74 } 75 76 Glib::Dispatcher& Gobby::ProgressDialog::Thread::done_event() 77 { 78 return m_disp_done; 79 } 80 81 Glib::Dispatcher& Gobby::ProgressDialog::Thread::work_event() 82 { 83 return m_disp_work; 84 } 85 86 void Gobby::ProgressDialog::Thread::on_thread_entry() 87 { 88 try 89 { 90 // Call working function 91 m_entry_func(*this); 92 } 93 catch(Glib::Thread::Exit& e) 94 { 95 // No need to throw e futher, the thread exits anyhow 96 } 97 98 // If the caller told us to quit we remove us silently, otherwise we 99 // tell the caller that we have done what we were supposed to. 100 if(m_quit) 101 { 102 // TODO: The dispatcher's destructor writes an odd message to 103 // stdout, how to supress it? 104 // - armin, 10-04-2005 105 delete this; 106 } 107 else 108 { 109 m_thread = NULL; // ??? 110 m_disp_done.emit(); 111 } 112 } 113 24 114 Gobby::ProgressDialog::ProgressDialog(const Glib::ustring& title, 25 115 Gtk::Window& parent) 26 116 : Gtk::Dialog(title, parent, true, true), 27 m_lbl_state("", Gtk::ALIGN_CENTER), m_parent(parent) 117 m_lbl_state("", Gtk::ALIGN_CENTER), m_thread(NULL), 118 m_parent(parent) 28 119 { 29 120 get_vbox()->pack_start(m_lbl_state, Gtk::PACK_SHRINK); … … 38 129 Glib::signal_idle().connect( 39 130 sigc::mem_fun(*this, &ProgressDialog::on_idle) ); 40 m_disp_work.connect(41 sigc::mem_fun(*this, &ProgressDialog::on_work) );42 m_disp_done.connect(43 sigc::mem_fun(*this, &ProgressDialog::on_done) );44 131 45 132 show_all(); … … 48 135 Gobby::ProgressDialog::~ProgressDialog() 49 136 { 137 // Tell the thread to terminate itself when the dialog has been closed 138 // before the thread has finsihed. 139 if(m_thread != NULL) 140 m_thread->quit(); 50 141 } 51 142 … … 65 156 } 66 157 67 void Gobby::ProgressDialog::work() 68 { 69 m_disp_work.emit(); 70 } 71 72 void Gobby::ProgressDialog::on_thread() 73 { 74 // Exit thread if we have to quit 75 if(g_atomic_int_get(&m_quit) != 0) 158 void Gobby::ProgressDialog::work(Thread& thread) 159 { 160 // Make sure that the calling thread is the worker thread 161 thread.assert_running(); 162 thread.work_event().emit(); 163 } 164 165 void Gobby::ProgressDialog::lock(Thread& thread) 166 { 167 // Make sure that the calling thread is the worker thread, the main 168 // thread does not have to call this function because it is used by 169 // the worker thread before querieng data from the dialog. The only 170 // time the main thread is locking the mutex is when the user closes 171 // the dialog. 172 thread.assert_running(); 173 174 thread.lock(); 175 if(thread.quitting() ) 176 { 177 // Exit from the thread if the dialog has been destroys, the 178 // user is no more interested in what we have done (otherwise, 179 // he would not have closed the dialog). 180 thread.unlock(); 76 181 throw Glib::Thread::Exit(); 182 } 183 } 184 185 void Gobby::ProgressDialog::unlock(Thread& thread) 186 { 187 // Make sure that the calling thread is the worker thread. 188 thread.assert_running(); 189 thread.unlock(); 77 190 } 78 191 … … 83 196 void Gobby::ProgressDialog::on_done() 84 197 { 85 m_thread->join(); 198 // Delete thread on termination 199 delete m_thread; 86 200 m_thread = NULL; 87 201 } … … 89 203 void Gobby::ProgressDialog::on_response(int response_id) 90 204 { 91 // Is the thread working? 92 if(m_thread) 93 { 94 // Set text 95 m_lbl_state.set_text(_("Waiting for thread to finish...") ); 96 // Show text 97 while(Gtk::Main::events_pending() ) 98 Gtk::Main::iteration(); 99 // Tell thread to quit 100 g_atomic_int_add(&m_quit, 1); 101 // Wait for the thread 102 m_thread->join(); 205 // Tell the thread to terminate itself when the dialog has been closed 206 // before the thread has finsihed 207 /* if(m_thread != NULL) 208 { 209 m_thread->quit(); 103 210 m_thread = NULL; 104 } 211 }*/ 105 212 106 213 // Response … … 110 217 bool Gobby::ProgressDialog::on_idle() 111 218 { 112 // Launch the worker thread 113 m_quit = 0; 114 m_thread = Glib::Thread::create( 115 sigc::mem_fun(*this, &ProgressDialog::thread_entry), 116 true 117 ); 118 219 // Create the worker thread 220 m_thread = new Thread(); 221 222 // Connect dispatchers 223 m_thread->done_event().connect( 224 sigc::mem_fun(*this, &ProgressDialog::on_done) ); 225 m_thread->work_event().connect( 226 sigc::mem_fun(*this, &ProgressDialog::on_work) ); 227 228 // Launch the thread 229 m_thread->launch(sigc::mem_fun(*this, &ProgressDialog::on_thread) ); 119 230 return false; 120 231 } 121 232 122 void Gobby::ProgressDialog::thread_entry()123 {124 on_thread();125 m_disp_done.emit();126 }127
