/usr/include/assa-3.5/assa/Acceptor.h is in libassa-3.5-5-dev 3.5.1-6build1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | // -*- c++ -*-
//------------------------------------------------------------------------
// Acceptor.h
//------------------------------------------------------------------------
// Copyright (C) 1999 Vladislav Grinchenko
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Library General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//------------------------------------------------------------------------
#ifndef ACCEPTOR_H
#define ACCEPTOR_H
#include "assa/Logger.h"
#include "assa/EventHandler.h"
#include "assa/Address.h"
#include "assa/Reactor.h"
#include "assa/ServiceHandler.h"
/** @file Acceptor.h
Acceptor encapsulates generic strategy for accepting TPC/IP connection
requests.
This abstract class implementes the generic strategy for passive
initializing communication services.
SERVICE_HANDLER is the type of service. It shall be a type derived
from ServiceHandler interface class.
PEER_ACCEPTOR is the type of concrete Socket class - particular
transport mechanism used by the Acceptor to passively establish
the connection. It should be derived from Socket interface class.
@see Reactor
@see ServiceHandler
*/
namespace ASSA {
template<class SERVICE_HANDLER, class PEER_ACCEPTOR>
class Acceptor : public virtual EventHandler
{
public:
/** Default constructor.
@param r_ Reactor to use
*/
Acceptor (Reactor* r_);
/** Do-nothing destructor. Underlying PEER_ACCEPTOR stream
will be closed during its own destruction sequence.
*/
virtual ~Acceptor ();
/** Initialize listener endpoint and Acceptor with Reactor.
Derive classes can change this strategy by overloading
this method.
@return 0 on success, -1 on error. An error can be if
either PEER_ACCEPTOR's open() or bind() failed.
*/
virtual int open (const Address& local_addr_);
/** Close PEER_ACCEPTOR stream.
@return 0 on success, -1 on error.
*/
virtual int close (void);
/** Callback invoked by Reactor when new connection requests
is detected. Default strategy is to accept ALL awaiting
incoming connections at once. Derived class can change
this strategy by overloading this method.
@return 0 on success, -1 on error. Returning -1 will
effectively instruct Reactor to remove this Handler from
the Reactor.
*/
int handle_read (int fd);
/** Callback invoked by Reactor if PEER_ACCEPTOR stream
went bad, or Reactor has been commanded to stop event processing.
This method should always return -1, if stream cannot be repared.
Derived class can change this strategy by overloading
this method. If called object is other then Reactor, an
explicit call to Reactor::removeHandler (this->id()) is required.
By default behavior, Acceptor will destroy itself.
@return -1 always
*/
virtual int handle_close (int fd);
protected:
/**
Defines creation strategy for ServiceHandler.
@return pointer to SERVICE_HANDLER
*/
virtual SERVICE_HANDLER* makeServiceHandler (PEER_ACCEPTOR* sock_);
/**
Default strategy is to accept new connection. Derived
class can change this strategy by overloading this method.
@param new_socket_ On return will have a pointer to
newly created PEER_STREAM, or =0 if failed
@return 0 on success, -1 on error.
*/
virtual int acceptServiceHandler (PEER_ACCEPTOR*& new_socket_);
/** Defines the concurrency strategy. Default is to create
SERVICE_HANDLERin current process(thread), call its open()
methid and let Reactor handle its I/O events.
Derived class changes this strategy by overloading this class.
@param new_socket_ [in] PEER_STREAM pointer to activate
@return 0 on success, -1 on error.
*/
virtual int activateServiceHandler (PEER_ACCEPTOR* new_socket_);
protected:
/** Underlying communication stream.
*/
PEER_ACCEPTOR m_listenSocket;
private:
/** Reactor to use.
*/
Reactor* m_reactor;
};
// Convenience definitions
#define SH SERVICE_HANDLER
#define PA PEER_ACCEPTOR
//------------------------------------------------------------------------------
// Template member functions definitions
//------------------------------------------------------------------------------
template<class SH, class PA>
inline
Acceptor<SH, PA>::
Acceptor (Reactor* r_)
: m_reactor (r_)
{
trace("Acceptor::Acceptor");
}
template<class SH, class PA>
inline
Acceptor<SH, PA>::
~Acceptor ()
{
trace("Acceptor::~Acceptor");
}
template<class SH, class PA>
inline int
Acceptor<SH, PA>::
close (void)
{
trace("Acceptor::close");
m_listenSocket.close ();
return 0;
}
template<class SH, class PA>
inline int
Acceptor<SH, PA>::
handle_close (int /* fd */)
{
trace("Acceptor::handle_close");
// Reactor::get_instance ()->removeHandler (this->id());
// NOT IMPLEMENTED: This spot requires validation
// whether Acceptor is created on the heap or in
// automatic memory.
DL ((REACT,"Deleted acceptor \"%s\"\n", get_id ().c_str ()));
delete this;
return -1;
}
template<class SH, class PA>
inline SERVICE_HANDLER*
Acceptor<SH, PA>::
makeServiceHandler (PEER_ACCEPTOR* sock_)
{
trace("Acceptor<>::makeServiceHandler");
return new SERVICE_HANDLER (sock_);
}
template<class SH, class PA>
inline int
Acceptor<SH, PA>::
acceptServiceHandler (PEER_ACCEPTOR*& new_socket_)
{
trace("Acceptor::acceptServiceHandler");
new_socket_ = m_listenSocket.accept ();
return new_socket_ ? 0 : -1;
}
template<class SH, class PA> int
Acceptor<SH, PA>::
activateServiceHandler (PA* new_socket_)
{
trace("Acceptor::activateServiceHandler");
if (!new_socket_) {
return -1;
}
SH* sh = makeServiceHandler (new_socket_);
if (sh->open () < 0) {
sh->close ();
}
return 0;
}
template<class SH, class PA> int
Acceptor<SH, PA>::
open (const Address& local_addr_)
{
trace("Acceptor::open");
if ( !m_listenSocket.open (local_addr_.getAddress ()->sa_family) ) {
return -1;
}
if ( !m_listenSocket.bind (local_addr_) ) {
return -1;
}
m_reactor->registerIOHandler (
this, m_listenSocket.getHandler (), READ_EVENT);
DL((TRACE,"Opened acceptor for fd=%d\n",
m_listenSocket.getHandler ()));
return 0;
}
//------------------------------------------------------------------------------
// Accept all connections waiting in listen queue at once. This avoids going
// through Reactor's event loop for each new connection.
//------------------------------------------------------------------------------
template <class SH, class PA> int
Acceptor<SH, PA>::
handle_read (int fd_)
{
trace("Acceptor<>::handle_read");
FdSet mask;
timeval poll = {0, 0};
PA* new_socket = 0;
int fd = m_listenSocket.getHandler ();
if (fd != fd_) {
return -1;
}
do {
if ( acceptServiceHandler (new_socket) == -1 ) {
return -1;
}
if ( !activateServiceHandler (new_socket) == -1 ) {
return -1;
}
mask.reset ();
mask.setFd (fd);
}
while ((::select (fd+1, &mask, NULL, NULL, &poll) == 1));
return 0;
}
} // end namespace ASSA
#endif /* ACCEPTOR_H */
|