1//
2// TCPServer.cpp
3//
4// Library: Net
5// Package: TCPServer
6// Module: TCPServer
7//
8// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/Net/TCPServer.h"
16#include "Poco/Net/TCPServerDispatcher.h"
17#include "Poco/Net/TCPServerConnection.h"
18#include "Poco/Net/TCPServerConnectionFactory.h"
19#include "Poco/Timespan.h"
20#include "Poco/Exception.h"
21#include "Poco/ErrorHandler.h"
22
23
24using Poco::ErrorHandler;
25
26
27namespace Poco {
28namespace Net {
29
30
31//
32// TCPServerConnectionFilter
33//
34
35
36TCPServerConnectionFilter::~TCPServerConnectionFilter()
37{
38}
39
40
41//
42// TCPServer
43//
44
45
46TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::UInt16 portNumber, TCPServerParams::Ptr pParams):
47 _socket(ServerSocket(portNumber)),
48 _thread(threadName(_socket)),
49 _stopped(true)
50{
51 Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
52 if (pParams)
53 {
54 int toAdd = pParams->getMaxThreads() - pool.capacity();
55 if (toAdd > 0) pool.addCapacity(toAdd);
56 }
57 _pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams);
58
59}
60
61
62TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, const ServerSocket& socket, TCPServerParams::Ptr pParams):
63 _socket(socket),
64 _thread(threadName(socket)),
65 _stopped(true)
66{
67 Poco::ThreadPool& pool = Poco::ThreadPool::defaultPool();
68 if (pParams)
69 {
70 int toAdd = pParams->getMaxThreads() - pool.capacity();
71 if (toAdd > 0) pool.addCapacity(toAdd);
72 }
73 _pDispatcher = new TCPServerDispatcher(pFactory, pool, pParams);
74}
75
76
77TCPServer::TCPServer(TCPServerConnectionFactory::Ptr pFactory, Poco::ThreadPool& threadPool, const ServerSocket& socket, TCPServerParams::Ptr pParams):
78 _socket(socket),
79 _pDispatcher(new TCPServerDispatcher(pFactory, threadPool, pParams)),
80 _thread(threadName(socket)),
81 _stopped(true)
82{
83}
84
85
86TCPServer::~TCPServer()
87{
88 try
89 {
90 stop();
91 _pDispatcher->release();
92 }
93 catch (...)
94 {
95 poco_unexpected();
96 }
97}
98
99
100const TCPServerParams& TCPServer::params() const
101{
102 return _pDispatcher->params();
103}
104
105
106void TCPServer::start()
107{
108 poco_assert (_stopped);
109
110 _stopped = false;
111 _thread.start(*this);
112}
113
114
115void TCPServer::stop()
116{
117 if (!_stopped)
118 {
119 _stopped = true;
120 _thread.join();
121 _pDispatcher->stop();
122 }
123}
124
125
126void TCPServer::run()
127{
128 while (!_stopped)
129 {
130 Poco::Timespan timeout(250000);
131 try
132 {
133 if (_socket.poll(timeout, Socket::SELECT_READ))
134 {
135 try
136 {
137 StreamSocket ss = _socket.acceptConnection();
138
139 if (!_pConnectionFilter || _pConnectionFilter->accept(ss))
140 {
141 // enable nodelay per default: OSX really needs that
142#if defined(POCO_OS_FAMILY_UNIX)
143 if (ss.address().family() != AddressFamily::UNIX_LOCAL)
144#endif
145 {
146 ss.setNoDelay(true);
147 }
148 _pDispatcher->enqueue(ss);
149 }
150 }
151 catch (Poco::Exception& exc)
152 {
153 ErrorHandler::handle(exc);
154 }
155 catch (std::exception& exc)
156 {
157 ErrorHandler::handle(exc);
158 }
159 catch (...)
160 {
161 ErrorHandler::handle();
162 }
163 }
164 }
165 catch (Poco::Exception& exc)
166 {
167 ErrorHandler::handle(exc);
168 // possibly a resource issue since poll() failed;
169 // give some time to recover before trying again
170 Poco::Thread::sleep(50);
171 }
172 }
173}
174
175
176int TCPServer::currentThreads() const
177{
178 return _pDispatcher->currentThreads();
179}
180
181
182int TCPServer::maxThreads() const
183{
184 return _pDispatcher->maxThreads();
185}
186
187
188int TCPServer::totalConnections() const
189{
190 return _pDispatcher->totalConnections();
191}
192
193
194int TCPServer::currentConnections() const
195{
196 return _pDispatcher->currentConnections();
197}
198
199
200int TCPServer::maxConcurrentConnections() const
201{
202 return _pDispatcher->maxConcurrentConnections();
203}
204
205
206int TCPServer::queuedConnections() const
207{
208 return _pDispatcher->queuedConnections();
209}
210
211
212int TCPServer::refusedConnections() const
213{
214 return _pDispatcher->refusedConnections();
215}
216
217
218void TCPServer::setConnectionFilter(const TCPServerConnectionFilter::Ptr& pConnectionFilter)
219{
220 poco_assert (_stopped);
221
222 _pConnectionFilter = pConnectionFilter;
223}
224
225
226std::string TCPServer::threadName(const ServerSocket& socket)
227{
228#if _WIN32_WCE == 0x0800
229 // Workaround for WEC2013: only the first call to getsockname()
230 // succeeds. To mitigate the impact of this bug, do not call
231 // socket.address(), which calls getsockname(), here.
232 std::string name("TCPServer");
233 #pragma message("Using WEC2013 getsockname() workaround in TCPServer::threadName(). Remove when no longer needed.")
234#else
235 std::string name("TCPServer: ");
236 name.append(socket.address().toString());
237#endif
238 return name;
239
240}
241
242
243} } // namespace Poco::Net
244