rcpp_framework/core/loops/acceptor.cpp

86 lines
1.8 KiB
C++
Raw Normal View History

2021-06-17 14:43:29 +02:00
/**
*
* Acceptor.cc
* An Tao
*
* Public header file in trantor lib.
*
* Copyright 2018, An Tao. All rights reserved.
* Use of this source code is governed by a BSD-style license
* that can be found in the License file.
*
*
*/
2022-02-10 01:24:36 +01:00
#include "acceptor.h"
2021-06-17 14:43:29 +02:00
using namespace trantor;
#ifndef O_CLOEXEC
#define O_CLOEXEC O_NOINHERIT
#endif
Acceptor::Acceptor(EventLoop *loop,
const InetAddress &addr,
bool reUseAddr,
bool reUsePort)
2021-06-17 14:43:29 +02:00
:
2021-06-17 14:43:29 +02:00
#ifndef _WIN32
idleFd_(::open("/dev/null", O_RDONLY | O_CLOEXEC)),
2021-06-17 14:43:29 +02:00
#endif
sock_(
Socket::createNonblockingSocketOrDie(addr.getSockAddr()->sa_family)),
addr_(addr),
loop_(loop),
acceptChannel_(loop, sock_.fd()) {
sock_.setReuseAddr(reUseAddr);
sock_.setReusePort(reUsePort);
sock_.bindAddress(addr_);
acceptChannel_.setReadCallback(std::bind(&Acceptor::readCallback, this));
if (addr_.toPort() == 0) {
addr_ = InetAddress{ Socket::getLocalAddr(sock_.fd()) };
}
2021-06-17 14:43:29 +02:00
}
Acceptor::~Acceptor() {
acceptChannel_.disableAll();
acceptChannel_.remove();
2021-06-17 14:43:29 +02:00
#ifndef _WIN32
::close(idleFd_);
2021-06-17 14:43:29 +02:00
#endif
}
void Acceptor::listen() {
loop_->assertInLoopThread();
sock_.listen();
acceptChannel_.enableReading();
2021-06-17 14:43:29 +02:00
}
void Acceptor::readCallback() {
InetAddress peer;
int newsock = sock_.accept(&peer);
if (newsock >= 0) {
if (newConnectionCallback_) {
newConnectionCallback_(newsock, peer);
} else {
2021-06-17 14:43:29 +02:00
#ifndef _WIN32
::close(newsock);
2021-06-17 14:43:29 +02:00
#else
closesocket(newsock);
2021-06-17 14:43:29 +02:00
#endif
}
} else {
LOG_SYSERR << "Accpetor::readCallback";
2021-06-17 14:43:29 +02:00
// Read the section named "The special problem of
// accept()ing when you can't" in libev's doc.
// By Marc Lehmann, author of libev.
/// errno is thread safe
#ifndef _WIN32
if (errno == EMFILE) {
::close(idleFd_);
idleFd_ = sock_.accept(&peer);
::close(idleFd_);
idleFd_ = ::open("/dev/null", O_RDONLY | O_CLOEXEC);
}
2021-06-17 14:43:29 +02:00
#endif
}
2021-06-17 14:43:29 +02:00
}