libassa  3.5.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Acceptor.h
Go to the documentation of this file.
1 // -*- c++ -*-
2 //------------------------------------------------------------------------
3 // Acceptor.h
4 //------------------------------------------------------------------------
5 // Copyright (C) 1999 Vladislav Grinchenko
6 //
7 // This library is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU Library General Public
9 // License as published by the Free Software Foundation; either
10 // version 2 of the License, or (at your option) any later version.
11 //------------------------------------------------------------------------
12 #ifndef ACCEPTOR_H
13 #define ACCEPTOR_H
14 
15 #include "assa/Logger.h"
16 #include "assa/EventHandler.h"
17 #include "assa/Address.h"
18 #include "assa/Reactor.h"
19 #include "assa/ServiceHandler.h"
20 
40 namespace ASSA {
41 
42 template<class SERVICE_HANDLER, class PEER_ACCEPTOR>
43 class Acceptor : public virtual EventHandler
44 {
45 public:
49  Acceptor (Reactor* r_);
50 
54  virtual ~Acceptor ();
55 
63  virtual int open (const Address& local_addr_);
64 
68  virtual int close (void);
69 
79  int handle_read (int fd);
80 
91  virtual int handle_close (int fd);
92 
93 protected:
98  virtual SERVICE_HANDLER* makeServiceHandler (PEER_ACCEPTOR* sock_);
99 
108  virtual int acceptServiceHandler (PEER_ACCEPTOR*& new_socket_);
109 
118  virtual int activateServiceHandler (PEER_ACCEPTOR* new_socket_);
119 
120 protected:
123  PEER_ACCEPTOR m_listenSocket;
124 
125 private:
126 
130 };
131 
132 // Convenience definitions
133 
134 #define SH SERVICE_HANDLER
135 #define PA PEER_ACCEPTOR
136 
137 //------------------------------------------------------------------------------
138 // Template member functions definitions
139 //------------------------------------------------------------------------------
140 
141 template<class SH, class PA>
142 inline
145  : m_reactor (r_)
146 {
147  trace("Acceptor::Acceptor");
148 }
149 
150 template<class SH, class PA>
151 inline
154 {
155  trace("Acceptor::~Acceptor");
156 }
157 
158 template<class SH, class PA>
159 inline int
161 close (void)
162 {
163  trace("Acceptor::close");
164  m_listenSocket.close ();
165  return 0;
166 }
167 
168 template<class SH, class PA>
169 inline int
171 handle_close (int /* fd */)
172 {
173  trace("Acceptor::handle_close");
174 
175  // Reactor::get_instance ()->removeHandler (this->id());
176 
177  // NOT IMPLEMENTED: This spot requires validation
178  // whether Acceptor is created on the heap or in
179  // automatic memory.
180  DL ((REACT,"Deleted acceptor \"%s\"\n", get_id ().c_str ()));
181  delete this;
182  return -1;
183 }
184 
185 template<class SH, class PA>
186 inline SERVICE_HANDLER*
188 makeServiceHandler (PEER_ACCEPTOR* sock_)
189 {
190  trace("Acceptor<>::makeServiceHandler");
191 
192  return new SERVICE_HANDLER (sock_);
193 }
194 
195 template<class SH, class PA>
196 inline int
198 acceptServiceHandler (PEER_ACCEPTOR*& new_socket_)
199 {
200  trace("Acceptor::acceptServiceHandler");
201 
202  new_socket_ = m_listenSocket.accept ();
203  return new_socket_ ? 0 : -1;
204 }
205 
206 template<class SH, class PA> int
208 activateServiceHandler (PA* new_socket_)
209 {
210  trace("Acceptor::activateServiceHandler");
211 
212  if (!new_socket_) {
213  return -1;
214  }
215  SH* sh = makeServiceHandler (new_socket_);
216  if (sh->open () < 0) {
217  sh->close ();
218  }
219  return 0;
220 }
221 
222 template<class SH, class PA> int
224 open (const Address& local_addr_)
225 {
226  trace("Acceptor::open");
227 
228  if ( !m_listenSocket.open (local_addr_.getAddress ()->sa_family) ) {
229  return -1;
230  }
231 
232  if ( !m_listenSocket.bind (local_addr_) ) {
233  return -1;
234  }
235 
236  m_reactor->registerIOHandler (
237  this, m_listenSocket.getHandler (), READ_EVENT);
238 
239  DL((TRACE,"Opened acceptor for fd=%d\n",
240  m_listenSocket.getHandler ()));
241 
242  return 0;
243 }
244 
245 //------------------------------------------------------------------------------
246 // Accept all connections waiting in listen queue at once. This avoids going
247 // through Reactor's event loop for each new connection.
248 //------------------------------------------------------------------------------
249 
250 template <class SH, class PA> int
252 handle_read (int fd_)
253 {
254  trace("Acceptor<>::handle_read");
255 
256  FdSet mask;
257  timeval poll = {0, 0};
258  PA* new_socket = 0;
259 
260  int fd = m_listenSocket.getHandler ();
261 
262  if (fd != fd_) {
263  return -1;
264  }
265 
266  do {
267  if ( acceptServiceHandler (new_socket) == -1 ) {
268  return -1;
269  }
270  if ( !activateServiceHandler (new_socket) == -1 ) {
271  return -1;
272  }
273  mask.reset ();
274  mask.setFd (fd);
275  }
276  while ((::select (fd+1, &mask, NULL, NULL, &poll) == 1));
277 
278  return 0;
279 }
280 
281 } // end namespace ASSA
282 
283 #endif /* ACCEPTOR_H */