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 
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 /** 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 
75 void
76 ConnectionDispatcher::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  */
92 void
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  */
108 void
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  */
135 ConnectionDispatcher::operator bool()
136 {
137  return (client_ && client_->connected());
138 }
139 
140 /** Internal event handler.
141  * Called by dispatcher to emit signal.
142  */
143 void
145 {
146  signal_connected_.emit();
147 }
148 
149 /** Internal event handler.
150  * Called by dispatcher to emit signal.
151  */
152 void
154 {
155  signal_disconnected_.emit();
156 }
157 
158 /** Internal event handler.
159  * Called by dispatcher to emit signal.
160  */
161 void
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 
174 void
175 ConnectionDispatcher::deregistered(unsigned int id) noexcept
176 {
177  // ignored
178 }
179 
180 void
182 {
183  m->ref();
184  queue_message_received_.push_locked(m);
185  dispatcher_message_received_();
186 }
187 
188 void
189 ConnectionDispatcher::connection_died(unsigned int id) noexcept
190 {
191  dispatcher_disconnected_();
192 }
193 
194 void
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  */
205 sigc::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  */
215 sigc::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  */
226 sigc::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.