5 #include "localserver.h" 11 #include <Cutelyst/Engine> 14 #include <QSocketNotifier> 18 # include <sys/socket.h> 23 inline int cutelyst_safe_accept(
int s,
struct sockaddr *addr, uint *addrlen,
int flags = 0)
25 Q_ASSERT((flags & ~O_NONBLOCK) == 0);
28 # ifdef QT_THREADSAFE_CLOEXEC 30 int sockflags = SOCK_CLOEXEC;
31 if (flags & O_NONBLOCK) {
32 sockflags |= SOCK_NONBLOCK;
34 # if defined(Q_OS_NETBSD) 35 fd = ::paccept(s, addr, static_cast<socklen_t *>(addrlen), NULL, sockflags);
37 fd = ::accept4(s, addr, static_cast<socklen_t *>(addrlen), sockflags);
41 fd = ::accept(s, addr, static_cast<socklen_t *>(addrlen));
46 ::fcntl(fd, F_SETFD, FD_CLOEXEC);
49 if (flags & O_NONBLOCK) {
50 ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
68 void LocalServer::setProtocol(
Protocol *protocol)
70 m_protocol = protocol;
76 server->setProtocol(m_protocol);
77 server->m_engine = engine;
80 server->m_socket = socket();
82 server->m_socketNotifier->setEnabled(
false);
83 connect(server->m_socketNotifier,
86 &LocalServer::socketNotifierActivated);
88 if (server->listen(socket())) {
89 server->pauseAccepting();
91 qFatal(
"Failed to set server socket descriptor");
95 connect(engine, &ServerEngine::started, server, &LocalServer::resumeAccepting);
96 connect(engine, &ServerEngine::shutdown, server, &LocalServer::shutdown);
101 void LocalServer::pauseAccepting()
103 auto notifier = socketDescriptorNotifier();
105 notifier->setEnabled(
false);
109 void LocalServer::resumeAccepting()
114 auto notifier = socketDescriptorNotifier();
116 notifier->setEnabled(
true);
121 void LocalServer::incomingConnection(quintptr handle)
124 sock->protoData = m_protocol->createData(sock);
127 sock->timeout =
false;
128 sock->proto->parse(sock, sock);
130 connect(sock, &LocalSocket::finished,
this, [
this, sock]() {
132 if (--m_processing == 0) {
133 m_engine->stopSocketTimeout();
137 if (Q_LIKELY(sock->setSocketDescriptor(qintptr(handle)))) {
138 sock->proto = m_protocol;
140 sock->serverAddress =
"localhost"_ba;
141 if (++m_processing) {
142 m_engine->startSocketTimeout();
149 qintptr LocalServer::socket()
const 153 return notifier->
socket();
159 void LocalServer::shutdown()
163 if (m_processing == 0) {
164 m_engine->serverShutdown();
167 for (
auto child : childrenL) {
170 connect(sock, &LocalSocket::finished,
this, [
this]() {
172 m_engine->serverShutdown();
175 m_engine->handleSocketShutdown(sock);
181 void LocalServer::timeoutConnections()
185 for (
auto child : childrenL) {
189 sock->connectionClose();
191 sock->timeout =
true;
198 Protocol *LocalServer::protocol()
const 211 for (
auto child : childrenL) {
223 void LocalServer::socketNotifierActivated()
225 if (-1 == m_socket) {
230 uint length =
sizeof(sockaddr_un);
231 int connectedSocket =
232 cutelyst_safe_accept(
int(m_socket), reinterpret_cast<sockaddr *>(&addr), &length);
233 if (-1 != connectedSocket) {
234 incomingConnection(quintptr(connectedSocket));
239 #include "moc_localserver.cpp" void activated(QSocketDescriptor socket, QSocketNotifier::Type type)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
const QObjectList & children() const const
The Cutelyst namespace holds all public Cutelyst API.
void setEnabled(bool enable)
T qobject_cast(QObject *object)
qintptr socket() const const