1//
2// SocketAcceptor.h
3//
4// Library: Net
5// Package: Reactor
6// Module: SocketAcceptor
7//
8// Definition of the SocketAcceptor class.
9//
10// Copyright (c) 2005-2006, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Net_SocketAcceptor_INCLUDED
18#define Net_SocketAcceptor_INCLUDED
19
20
21#include "Poco/Net/Net.h"
22#include "Poco/Net/SocketNotification.h"
23#include "Poco/Net/SocketReactor.h"
24#include "Poco/Net/ServerSocket.h"
25#include "Poco/Net/StreamSocket.h"
26#include "Poco/Observer.h"
27
28
29namespace Poco {
30namespace Net {
31
32
33template <class ServiceHandler>
34class SocketAcceptor
35 /// This class implements the Acceptor part of the
36 /// Acceptor-Connector design pattern.
37 ///
38 /// The Acceptor-Connector pattern has been described in the book
39 /// "Pattern Languages of Program Design 3", edited by Robert Martin,
40 /// Frank Buschmann and Dirk Riehle (Addison Wesley, 1997).
41 ///
42 /// The Acceptor-Connector design pattern decouples connection
43 /// establishment and service initialization in a distributed system
44 /// from the processing performed once a service is initialized.
45 /// This decoupling is achieved with three components: Acceptors,
46 /// Connectors and Service Handlers.
47 /// The SocketAcceptor passively waits for connection requests (usually
48 /// from a remote Connector) and establishes a connection upon
49 /// arrival of a connection requests. Also, a Service Handler is
50 /// initialized to process the data arriving via the connection in
51 /// an application-specific way.
52 ///
53 /// The SocketAcceptor sets up a ServerSocket and registers itself
54 /// for a ReadableNotification, denoting an incoming connection request.
55 ///
56 /// When the ServerSocket becomes readable the SocketAcceptor accepts
57 /// the connection request and creates a ServiceHandler to
58 /// service the connection.
59 ///
60 /// The ServiceHandler class must provide a constructor that
61 /// takes a StreamSocket and a SocketReactor as arguments,
62 /// e.g.:
63 /// MyServiceHandler(const StreamSocket& socket, ServiceReactor& reactor)
64 ///
65 /// When the ServiceHandler is done, it must destroy itself.
66 ///
67 /// Subclasses can override the createServiceHandler() factory method
68 /// if special steps are necessary to create a ServiceHandler object.
69{
70public:
71 typedef Poco::Observer<SocketAcceptor, ReadableNotification> Observer;
72
73 explicit SocketAcceptor(ServerSocket& socket):
74 _socket(socket),
75 _pReactor(0)
76 /// Creates a SocketAcceptor, using the given ServerSocket.
77 {
78 }
79
80 SocketAcceptor(ServerSocket& socket, SocketReactor& reactor):
81 _socket(socket),
82 _pReactor(&reactor)
83 /// Creates a SocketAcceptor, using the given ServerSocket.
84 /// The SocketAcceptor registers itself with the given SocketReactor.
85 {
86 _pReactor->addEventHandler(_socket, Observer(*this, &SocketAcceptor::onAccept));
87 }
88
89 virtual ~SocketAcceptor()
90 /// Destroys the SocketAcceptor.
91 {
92 try
93 {
94 if (_pReactor)
95 {
96 _pReactor->removeEventHandler(_socket, Observer(*this, &SocketAcceptor::onAccept));
97 }
98 }
99 catch (...)
100 {
101 poco_unexpected();
102 }
103 }
104
105 void setReactor(SocketReactor& reactor)
106 /// Sets the reactor for this acceptor.
107 {
108 registerAcceptor(reactor);
109 }
110
111 virtual void registerAcceptor(SocketReactor& reactor)
112 /// Registers the SocketAcceptor with a SocketReactor.
113 ///
114 /// A subclass can override this function to e.g.
115 /// register an event handler for timeout event.
116 ///
117 /// If acceptor was constructed without providing reactor to it,
118 /// the override of this method must either call the base class
119 /// implementation or directly register the accept handler with
120 /// the reactor.
121 {
122 _pReactor = &reactor;
123 if (!_pReactor->hasEventHandler(_socket, Observer(*this, &SocketAcceptor::onAccept)))
124 {
125 _pReactor->addEventHandler(_socket, Observer(*this, &SocketAcceptor::onAccept));
126 }
127 }
128
129 virtual void unregisterAcceptor()
130 /// Unregisters the SocketAcceptor.
131 ///
132 /// A subclass can override this function to e.g.
133 /// unregister its event handler for a timeout event.
134 ///
135 /// If the accept handler was registered with the reactor,
136 /// the overriding method must either call the base class
137 /// implementation or directly unregister the accept handler.
138 {
139 if (_pReactor)
140 {
141 _pReactor->removeEventHandler(_socket, Observer(*this, &SocketAcceptor::onAccept));
142 }
143 }
144
145 void onAccept(ReadableNotification* pNotification)
146 /// Accepts connection and creates event handler.
147 {
148 pNotification->release();
149 StreamSocket sock = _socket.acceptConnection();
150 _pReactor->wakeUp();
151 createServiceHandler(sock);
152 }
153
154protected:
155 virtual ServiceHandler* createServiceHandler(StreamSocket& socket)
156 /// Create and initialize a new ServiceHandler instance.
157 ///
158 /// Subclasses can override this method.
159 {
160 return new ServiceHandler(socket, *_pReactor);
161 }
162
163 SocketReactor* reactor()
164 /// Returns a pointer to the SocketReactor where
165 /// this SocketAcceptor is registered.
166 ///
167 /// The pointer may be null.
168 {
169 return _pReactor;
170 }
171
172 Socket& socket()
173 /// Returns a reference to the SocketAcceptor's socket.
174 {
175 return _socket;
176 }
177
178private:
179 SocketAcceptor();
180 SocketAcceptor(const SocketAcceptor&);
181 SocketAcceptor& operator = (const SocketAcceptor&);
182
183 ServerSocket _socket;
184 SocketReactor* _pReactor;
185};
186
187
188} } // namespace Poco::Net
189
190
191#endif // Net_SocketAcceptor_INCLUDED
192