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 
31 using namespace fawkes;
32 
33 namespace 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  */
56 FuseServer::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 
112 void
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  */
127 void
129 {
130  dead_clients_.push_back_locked(client);
131  wakeup();
132 }
133 
134 void
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
fawkes::ThreadCollector
Definition: thread_collector.h:38
fawkes::ThreadCollector::remove
virtual void remove(ThreadList &tl)=0
firevision::FuseServer::loop
virtual void loop()
Code to execute in the thread.
Definition: fuse_server.cpp:134
firevision::FuseServer::add_connection
virtual void add_connection(fawkes::StreamSocket *s)
Definition: fuse_server.cpp:112
fawkes::LockList
Definition: thread.h:42
fawkes::ThreadCollector::add
virtual void add(ThreadList &tl)=0
fawkes
firevision::FuseServer::connection_died
void connection_died(FuseServerClientThread *client)
Connection died.
Definition: fuse_server.cpp:127
fawkes::NetworkAcceptorThread
Definition: acceptor_thread.h:41
firevision::FuseServerClientThread
Definition: fuse_server_client_thread.h:43
fawkes::Thread
Definition: thread.h:44
fawkes::Thread::start
void start(bool wait=true)
Call this method to start the thread.
Definition: thread.cpp:503
firevision::FuseServer::~FuseServer
virtual ~FuseServer()
Destructor.
Definition: fuse_server.cpp:85
fawkes::StreamSocket
Definition: stream.h:35