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 <cstdlib>
28#include <cstring>
29
30namespace 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/** Constructor.
52 * @param cid component ID to register this dispatcher for. This is relevant if
53 * you want to use the message received signal!
54 * @param hostname hostname to connect to
55 * @param port port to connect to
56 */
58 unsigned short int port,
59 unsigned int cid)
60{
61 cid_ = cid;
62 client_ = new FawkesNetworkClient(hostname, port);
63 client_->register_handler(this, cid_);
64 client_owned_ = true;
65
66 connect_signals();
67}
68
69/** Destructor. */
71{
72 set_client(NULL);
73}
74
75void
76ConnectionDispatcher::connect_signals()
77{
78 dispatcher_connected_.connect(
80 dispatcher_disconnected_.connect(sigc::mem_fun(*this, &ConnectionDispatcher::on_connection_died));
81 dispatcher_message_received_.connect(
82 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 */
92void
94{
95 if (client_) {
96 client_->deregister_handler(cid_);
97 client_->register_handler(this, cid);
98 }
99 cid_ = cid;
100}
101
102/** Set Fawkes network client.
103 * The instance you set is not owned by the ConnectionDispatcher, it's only
104 * used. You have to delete it when finished. Similarly you have to make sure that
105 * the client is valid as long as it is set on the dispatcher.
106 * @param client Fawkes network client to set.
107 */
108void
110{
111 if (client_)
112 client_->deregister_handler(cid_);
113 if (client_owned_) {
114 delete client_;
115 }
116 client_owned_ = false;
117 client_ = client;
118 if (client_)
119 client_->register_handler(this, cid_);
120}
121
122/** Get client.
123 * @return associated Fawkes network client.
124 */
127{
128 return client_;
129}
130
131/** Check if client is set and connection has been established.
132 * @return true if a client exists and a connection is established, false
133 * otherwise.
134 */
135ConnectionDispatcher::operator bool()
136{
137 return (client_ && client_->connected());
138}
139
140/** Internal event handler.
141 * Called by dispatcher to emit signal.
142 */
143void
145{
146 signal_connected_.emit();
147}
148
149/** Internal event handler.
150 * Called by dispatcher to emit signal.
151 */
152void
154{
155 signal_disconnected_.emit();
156}
157
158/** Internal event handler.
159 * Called by dispatcher to emit signal.
160 */
161void
163{
164 queue_message_received_.lock();
165 while (!queue_message_received_.empty()) {
166 FawkesNetworkMessage *msg = queue_message_received_.front();
167 signal_message_received_.emit(msg);
168 msg->unref();
169 queue_message_received_.pop();
170 }
171 queue_message_received_.unlock();
172}
173
174void
175ConnectionDispatcher::deregistered(unsigned int id) noexcept
176{
177 // ignored
178}
179
180void
182{
183 m->ref();
184 queue_message_received_.push_locked(m);
185 dispatcher_message_received_();
186}
187
188void
190{
191 dispatcher_disconnected_();
192}
193
194void
196{
197 dispatcher_connected_();
198}
199
200/** Get "message received" signal.
201 * The "message received" signal is emitted whenever a FawkesNetworkMessage has
202 * been received.
203 * @return "message received" signal
204 */
205sigc::signal<void, FawkesNetworkMessage *>
207{
208 return signal_message_received_;
209}
210
211/** Get "connected" signal.
212 * The "connected" signal is emitted when the connection has been established.
213 * @return "connected" signal
214 */
215sigc::signal<void>
217{
218 return signal_connected_;
219}
220
221/** Get "disconnected" signal.
222 * The "disconnected" signal is emitted when the connection has died, for example
223 * because the other peer closed the connection.
224 * @return "disconnected" signal
225 */
226sigc::signal<void>
228{
229 return signal_disconnected_;
230}
231
232} // end of namespace fawkes
virtual void on_connection_died()
Internal event handler.
void set_client(FawkesNetworkClient *client)
Set Fawkes network client.
ConnectionDispatcher(unsigned int cid=FAWKES_CID_OBSERVER_MODE)
Constructor.
virtual void connection_established(unsigned int id) noexcept
Client has established a connection.
void set_cid(unsigned int cid)
Set component ID.
virtual ~ConnectionDispatcher()
Destructor.
sigc::signal< void > signal_connected()
Get "connected" signal.
FawkesNetworkClient * get_client()
Get client.
virtual void on_message_received()
Internal event handler.
sigc::signal< void, FawkesNetworkMessage * > signal_message_received()
Get "message received" signal.
virtual void deregistered(unsigned int id) noexcept
This handler has been deregistered.
virtual void inbound_received(FawkesNetworkMessage *m, unsigned int id) noexcept
Called for incoming messages.
sigc::signal< void > signal_disconnected()
Get "disconnected" signal.
virtual void on_connection_established()
Internal event handler.
virtual void connection_died(unsigned int id) noexcept
Client connection died.
Simple Fawkes network client.
Definition: client.h:52
void register_handler(FawkesNetworkClientHandler *handler, unsigned int component_id)
Register handler.
Definition: client.cpp:658
void deregister_handler(unsigned int component_id)
Deregister handler.
Definition: client.cpp:676
Representation of a message that is sent over the network.
Definition: message.h:77
void lock() const
Lock queue.
Definition: lock_queue.h:114
void unlock() const
Unlock list.
Definition: lock_queue.h:128
void unref()
Decrement reference count and conditionally delete this instance.
Definition: refcount.cpp:95
Fawkes library namespace.