Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * connection_dispatcher.cpp - Network connection listener and dispatcher 00004 * 00005 * Created: Mon Oct 20 15:06:28 2008 00006 * Copyright 2008 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 00022 */ 00023 00024 #include <gui_utils/connection_dispatcher.h> 00025 #include <netcomm/fawkes/client.h> 00026 00027 #include <cstring> 00028 #include <cstdlib> 00029 00030 namespace fawkes { 00031 00032 /** @class ConnectionDispatcher <gui_utils/connection_dispatcher.h> 00033 * Watches network client events and dispatches them as signals. 00034 * @author Tim Niemueller 00035 */ 00036 00037 /** Constructor. 00038 * @param cid component ID to register this dispatcher for. This is relevant if 00039 * you want to use the message received signal! 00040 */ 00041 ConnectionDispatcher::ConnectionDispatcher(unsigned int cid) 00042 { 00043 __cid = cid; 00044 __client = new FawkesNetworkClient(); 00045 __client->register_handler(this, __cid); 00046 __client_owned = true; 00047 00048 connect_signals(); 00049 } 00050 00051 00052 /** Constructor. 00053 * @param cid component ID to register this dispatcher for. This is relevant if 00054 * you want to use the message received signal! 00055 * @param hostname hostname to connect to 00056 * @param port port to connect to 00057 */ 00058 ConnectionDispatcher::ConnectionDispatcher(const char *hostname, 00059 unsigned short int port, 00060 unsigned int cid) 00061 { 00062 __cid = cid; 00063 __client = new FawkesNetworkClient(hostname, port); 00064 __client->register_handler(this, __cid); 00065 __client_owned = true; 00066 00067 connect_signals(); 00068 } 00069 00070 /** Destructor. */ 00071 ConnectionDispatcher::~ConnectionDispatcher() 00072 { 00073 set_client(NULL); 00074 } 00075 00076 00077 void 00078 ConnectionDispatcher::connect_signals() 00079 { 00080 __dispatcher_connected.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_connection_established)); 00081 __dispatcher_disconnected.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_connection_died)); 00082 __dispatcher_message_received.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_message_received)); 00083 } 00084 00085 /** Set component ID. 00086 * Set the component ID you want to register this connection dispatcher on. By 00087 * default the connection dispatcher uses the observer mode to only provide 00088 * connection status signals. If you want to use the dispatcher to be signaled 00089 * for incoming messages you have to set the appropriate component ID. 00090 * @param cid component ID 00091 */ 00092 void 00093 ConnectionDispatcher::set_cid(unsigned int cid) 00094 { 00095 if ( __client ) { 00096 __client->deregister_handler(__cid); 00097 __client->register_handler(this, cid); 00098 } 00099 __cid = cid; 00100 } 00101 00102 00103 /** Set Fawkes network client. 00104 * The instance you set is not owned by the ConnectionDispatcher, it's only 00105 * used. You have to delete it when finished. Similarly you have to make sure that 00106 * the client is valid as long as it is set on the dispatcher. 00107 * @param client Fawkes network client to set. 00108 */ 00109 void 00110 ConnectionDispatcher::set_client(FawkesNetworkClient *client) 00111 { 00112 if ( __client ) __client->deregister_handler(__cid); 00113 if ( __client_owned ) { 00114 delete __client; 00115 } 00116 __client_owned = false; 00117 __client = client; 00118 if ( __client ) __client->register_handler(this, __cid); 00119 } 00120 00121 00122 /** Get client. 00123 * @return associated Fawkes network client. 00124 */ 00125 FawkesNetworkClient * 00126 ConnectionDispatcher::get_client() 00127 { 00128 return __client; 00129 } 00130 00131 00132 /** Check if client is set and connection has been established. 00133 * @return true if a client exists and a connection is established, false 00134 * otherwise. 00135 */ 00136 ConnectionDispatcher::operator bool() 00137 { 00138 return (__client && __client->connected()); 00139 } 00140 00141 00142 /** Internal event handler. 00143 * Called by dispatcher to emit signal. 00144 */ 00145 void 00146 ConnectionDispatcher::on_connection_established() 00147 { 00148 __signal_connected.emit(); 00149 } 00150 00151 00152 /** Internal event handler. 00153 * Called by dispatcher to emit signal. 00154 */ 00155 void 00156 ConnectionDispatcher::on_connection_died() 00157 { 00158 __signal_disconnected.emit(); 00159 } 00160 00161 00162 /** Internal event handler. 00163 * Called by dispatcher to emit signal. 00164 */ 00165 void 00166 ConnectionDispatcher::on_message_received() 00167 { 00168 __queue_message_received.lock(); 00169 while (! __queue_message_received.empty()) { 00170 FawkesNetworkMessage *msg = __queue_message_received.front(); 00171 __signal_message_received.emit(msg); 00172 msg->unref(); 00173 __queue_message_received.pop(); 00174 } 00175 __queue_message_received.unlock(); 00176 } 00177 00178 00179 void 00180 ConnectionDispatcher::deregistered(unsigned int id) throw() 00181 { 00182 // ignored 00183 } 00184 00185 00186 void 00187 ConnectionDispatcher::inbound_received(FawkesNetworkMessage *m, unsigned int id) throw() 00188 { 00189 m->ref(); 00190 __queue_message_received.push_locked(m); 00191 __dispatcher_message_received(); 00192 } 00193 00194 00195 void 00196 ConnectionDispatcher::connection_died(unsigned int id) throw() 00197 { 00198 __dispatcher_disconnected(); 00199 } 00200 00201 00202 void 00203 ConnectionDispatcher::connection_established(unsigned int id) throw() 00204 { 00205 __dispatcher_connected(); 00206 } 00207 00208 00209 /** Get "message received" signal. 00210 * The "message received" signal is emitted whenever a FawkesNetworkMessage has 00211 * been received. 00212 * @return "message received" signal 00213 */ 00214 sigc::signal<void, FawkesNetworkMessage *> 00215 ConnectionDispatcher::signal_message_received() 00216 { 00217 return __signal_message_received; 00218 } 00219 00220 00221 /** Get "connected" signal. 00222 * The "connected" signal is emitted when the connection has been established. 00223 * @return "connected" signal 00224 */ 00225 sigc::signal<void> 00226 ConnectionDispatcher::signal_connected() 00227 { 00228 return __signal_connected; 00229 } 00230 00231 00232 /** Get "disconnected" signal. 00233 * The "disconnected" signal is emitted when the connection has died, for example 00234 * because the other peer closed the connection. 00235 * @return "disconnected" signal 00236 */ 00237 sigc::signal<void> 00238 ConnectionDispatcher::signal_disconnected() 00239 { 00240 return __signal_disconnected; 00241 } 00242 00243 } // end of namespace fawkes