Fawkes API  Fawkes Development Version
connection_dispatcher.cpp
1 
2 /***************************************************************************
3  * connection_dispatcher.cpp - Network connection listener and dispatcher
4  *
5  * Created: Mon Oct 20 15:06:28 2008
6  * Copyright 2008 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <gui_utils/connection_dispatcher.h>
25 #include <netcomm/fawkes/client.h>
26 
27 #include <cstring>
28 #include <cstdlib>
29 
30 namespace fawkes {
31 
32 /** @class ConnectionDispatcher <gui_utils/connection_dispatcher.h>
33  * Watches network client events and dispatches them as signals.
34  * @author Tim Niemueller
35  */
36 
37 /** Constructor.
38  * @param cid component ID to register this dispatcher for. This is relevant if
39  * you want to use the message received signal!
40  */
42 {
43  __cid = cid;
44  __client = new FawkesNetworkClient();
45  __client->register_handler(this, __cid);
46  __client_owned = true;
47 
48  connect_signals();
49 }
50 
51 
52 /** Constructor.
53  * @param cid component ID to register this dispatcher for. This is relevant if
54  * you want to use the message received signal!
55  * @param hostname hostname to connect to
56  * @param port port to connect to
57  */
59  unsigned short int port,
60  unsigned int cid)
61 {
62  __cid = cid;
63  __client = new FawkesNetworkClient(hostname, port);
64  __client->register_handler(this, __cid);
65  __client_owned = true;
66 
67  connect_signals();
68 }
69 
70 /** Destructor. */
72 {
73  set_client(NULL);
74 }
75 
76 
77 void
78 ConnectionDispatcher::connect_signals()
79 {
80  __dispatcher_connected.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_connection_established));
81  __dispatcher_disconnected.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_connection_died));
82  __dispatcher_message_received.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_message_received));
83 }
84 
85 /** Set component ID.
86  * Set the component ID you want to register this connection dispatcher on. By
87  * default the connection dispatcher uses the observer mode to only provide
88  * connection status signals. If you want to use the dispatcher to be signaled
89  * for incoming messages you have to set the appropriate component ID.
90  * @param cid component ID
91  */
92 void
94 {
95  if ( __client ) {
96  __client->deregister_handler(__cid);
97  __client->register_handler(this, cid);
98  }
99  __cid = cid;
100 }
101 
102 
103 /** Set Fawkes network client.
104  * The instance you set is not owned by the ConnectionDispatcher, it's only
105  * used. You have to delete it when finished. Similarly you have to make sure that
106  * the client is valid as long as it is set on the dispatcher.
107  * @param client Fawkes network client to set.
108  */
109 void
111 {
112  if ( __client ) __client->deregister_handler(__cid);
113  if ( __client_owned ) {
114  delete __client;
115  }
116  __client_owned = false;
117  __client = client;
118  if ( __client ) __client->register_handler(this, __cid);
119 }
120 
121 
122 /** Get client.
123  * @return associated Fawkes network client.
124  */
127 {
128  return __client;
129 }
130 
131 
132 /** Check if client is set and connection has been established.
133  * @return true if a client exists and a connection is established, false
134  * otherwise.
135  */
136 ConnectionDispatcher::operator bool()
137 {
138  return (__client && __client->connected());
139 }
140 
141 
142 /** Internal event handler.
143  * Called by dispatcher to emit signal.
144  */
145 void
147 {
148  __signal_connected.emit();
149 }
150 
151 
152 /** Internal event handler.
153  * Called by dispatcher to emit signal.
154  */
155 void
157 {
158  __signal_disconnected.emit();
159 }
160 
161 
162 /** Internal event handler.
163  * Called by dispatcher to emit signal.
164  */
165 void
167 {
168  __queue_message_received.lock();
169  while (! __queue_message_received.empty()) {
170  FawkesNetworkMessage *msg = __queue_message_received.front();
171  __signal_message_received.emit(msg);
172  msg->unref();
173  __queue_message_received.pop();
174  }
175  __queue_message_received.unlock();
176 }
177 
178 
179 void
180 ConnectionDispatcher::deregistered(unsigned int id) throw()
181 {
182  // ignored
183 }
184 
185 
186 void
188 {
189  m->ref();
190  __queue_message_received.push_locked(m);
191  __dispatcher_message_received();
192 }
193 
194 
195 void
197 {
198  __dispatcher_disconnected();
199 }
200 
201 
202 void
204 {
205  __dispatcher_connected();
206 }
207 
208 
209 /** Get "message received" signal.
210  * The "message received" signal is emitted whenever a FawkesNetworkMessage has
211  * been received.
212  * @return "message received" signal
213  */
214  sigc::signal<void, FawkesNetworkMessage *>
216 {
217  return __signal_message_received;
218 }
219 
220 
221 /** Get "connected" signal.
222  * The "connected" signal is emitted when the connection has been established.
223  * @return "connected" signal
224  */
225 sigc::signal<void>
227 {
228  return __signal_connected;
229 }
230 
231 
232 /** Get "disconnected" signal.
233  * The "disconnected" signal is emitted when the connection has died, for example
234  * because the other peer closed the connection.
235  * @return "disconnected" signal
236  */
237 sigc::signal<void>
239 {
240  return __signal_disconnected;
241 }
242 
243 } // end of namespace fawkes
sigc::signal< void > signal_disconnected()
Get "disconnected" signal.
sigc::signal< void > signal_connected()
Get "connected" signal.
Simple Fawkes network client.
Definition: client.h:52
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:99
void unlock() const
Unlock list.
Definition: lock_queue.h:131
Fawkes library namespace.
void register_handler(FawkesNetworkClientHandler *handler, unsigned int component_id)
Register handler.
Definition: client.cpp:646
Representation of a message that is sent over the network.
Definition: message.h:75
void set_client(FawkesNetworkClient *client)
Set Fawkes network client.
ConnectionDispatcher(unsigned int cid=FAWKES_CID_OBSERVER_MODE)
Constructor.
virtual void inbound_received(FawkesNetworkMessage *m, unsigned int id)
Called for incoming messages.
virtual void on_message_received()
Internal event handler.
virtual void on_connection_died()
Internal event handler.
virtual void connection_established(unsigned int id)
Client has established a connection.
void set_cid(unsigned int cid)
Set component ID.
virtual void connection_died(unsigned int id)
Client connection died.
virtual ~ConnectionDispatcher()
Destructor.
void push_locked(const Type &x)
Push element to queue with lock protection.
Definition: lock_queue.h:139
void lock() const
Lock queue.
Definition: lock_queue.h:115
virtual void on_connection_established()
Internal event handler.
void deregister_handler(unsigned int component_id)
Deregister handler.
Definition: client.cpp:665
sigc::signal< void, FawkesNetworkMessage * > signal_message_received()
Get "message received" signal.
bool connected() const
Check if connection is alive.
Definition: client.cpp:823
FawkesNetworkClient * get_client()
Get client.
virtual void deregistered(unsigned int id)
This handler has been deregistered.