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