Fawkes API Fawkes Development Version
fuse_server.cpp
1
2/***************************************************************************
3 * fuse_server.tcp - network image transport server interface
4 *
5 * Generated: Mon Mar 19 15:56:22 2007
6 * Copyright 2005-2007 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 <core/threading/thread_collector.h>
25#include <fvutils/net/fuse_server.h>
26#include <fvutils/net/fuse_server_client_thread.h>
27#include <netcomm/utils/acceptor_thread.h>
28
29#include <algorithm>
30
31using namespace fawkes;
32
33namespace firevision {
34
35/** @class FuseServer <fvutils/net/fuse_server.h>
36 * FireVision FUSE protocol server.
37 * The FuseServer will open a StreamSocket and listen on it for incoming
38 * connections. For each connection a client thread is started that will process
39 * all requests issued by the client.
40 *
41 * @ingroup FUSE
42 * @ingroup FireVision
43 * @author Tim Niemueller
44 */
45
46/** Constructor.
47 * @param enable_ipv4 true to listen on the IPv4 TCP port
48 * @param enable_ipv6 true to listen on the IPv6 TCP port
49 * @param listen_ipv4 IPv4 address to listen on for incoming connections,
50 * 0.0.0.0 to listen on any local address
51 * @param listen_ipv6 IPv6 address to listen on for incoming connections,
52 * :: to listen on any local address
53 * @param port Port to listen on for incoming connections
54 * @param collector optional thread collector
55 */
56FuseServer::FuseServer(bool enable_ipv4,
57 bool enable_ipv6,
58 const std::string &listen_ipv4,
59 const std::string &listen_ipv6,
60 unsigned short int port,
61 ThreadCollector * collector)
62: Thread("FuseServer", Thread::OPMODE_WAITFORWAKEUP)
63{
64 thread_collector_ = collector;
65
66 if (enable_ipv4) {
67 acceptor_threads_.push_back(new NetworkAcceptorThread(
68 this, Socket::IPv4, listen_ipv4, port, "FuseNetworkAcceptorThread"));
69 }
70 if (enable_ipv6) {
71 acceptor_threads_.push_back(new NetworkAcceptorThread(
72 this, Socket::IPv6, listen_ipv6, port, "FuseNetworkAcceptorThread"));
73 }
74 if (thread_collector_) {
75 for (size_t i = 0; i < acceptor_threads_.size(); ++i) {
76 thread_collector_->add(acceptor_threads_[i]);
77 }
78 } else {
79 for (size_t i = 0; i < acceptor_threads_.size(); ++i) {
80 acceptor_threads_[i]->start();
81 }
82 }
83}
84
85/** Destructor. */
87{
88 for (size_t i = 0; i < acceptor_threads_.size(); ++i) {
89 if (thread_collector_) {
90 thread_collector_->remove(acceptor_threads_[i]);
91 } else {
92 acceptor_threads_[i]->cancel();
93 acceptor_threads_[i]->join();
94 }
95 delete acceptor_threads_[i];
96 }
97 acceptor_threads_.clear();
98
99 for (cit_ = clients_.begin(); cit_ != clients_.end(); ++cit_) {
100 if (thread_collector_) {
101 // ThreadCollector::remove also stops the threads!
102 thread_collector_->remove(*cit_);
103 } else {
104 (*cit_)->cancel();
105 (*cit_)->join();
106 }
107 delete *cit_;
108 }
109 clients_.clear();
110}
111
112void
114{
115 FuseServerClientThread *client = new FuseServerClientThread(this, s);
116 if (thread_collector_) {
117 thread_collector_->add(client);
118 } else {
119 client->start();
120 }
121 clients_.push_back_locked(client);
122}
123
124/** Connection died.
125 * @param client client whose connection died
126 */
127void
129{
130 dead_clients_.push_back_locked(client);
131 wakeup();
132}
133
134void
136{
137 // Check for dead clients, cancel and join if there are any
138 dead_clients_.lock();
139 clients_.lock();
140
142
143 while (!dead_clients_.empty()) {
144 dcit = dead_clients_.begin();
145
146 if (thread_collector_) {
147 // ThreadCollector::remove also stops the threads!
148 thread_collector_->remove(*dcit);
149 } else {
150 (*dcit)->cancel();
151 (*dcit)->join();
152 }
153 if ((cit_ = find(clients_.begin(), clients_.end(), *dcit)) != clients_.end()) {
154 clients_.erase(cit_);
155 }
156
157 FuseServerClientThread *tc = *dcit;
158 dead_clients_.erase(dcit);
159 delete tc;
160 }
161
162 clients_.unlock();
163 dead_clients_.unlock();
164}
165
166} // end namespace firevision
List with a lock.
Definition: lock_list.h:45
Network Acceptor Thread.
TCP stream socket over IP.
Definition: stream.h:32
virtual void add(ThreadList &tl)=0
Add multiple threads.
virtual void remove(ThreadList &tl)=0
Remove multiple threads.
Thread class encapsulation of pthreads.
Definition: thread.h:46
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:499
virtual void add_connection(fawkes::StreamSocket *s) noexcept
Add an incoming connection.
virtual void loop()
Code to execute in the thread.
FuseServer(bool enable_ipv4, bool enable_ipv6, const std::string &listen_ipv4, const std::string &listen_ipv6, unsigned short int port, fawkes::ThreadCollector *collector=0)
Constructor.
Definition: fuse_server.cpp:56
void connection_died(FuseServerClientThread *client) noexcept
Connection died.
virtual ~FuseServer()
Destructor.
Definition: fuse_server.cpp:86
Fawkes library namespace.