5#include "localserver.h"
11#include <Cutelyst/Engine>
14#include <QSocketNotifier>
18# include <sys/socket.h>
23static inline int cutelyst_safe_accept(
int s,
struct sockaddr *addr, uint *addrlen,
int flags = 0);
35void LocalServer::setProtocol(
Protocol *protocol)
37 m_protocol = protocol;
42 auto server =
new LocalServer(m_wsgi, engine);
43 server->setProtocol(m_protocol);
44 server->m_engine = engine;
47 server->m_socket = socket();
49 server->m_socketNotifier->setEnabled(
false);
50 connect(server->m_socketNotifier,
53 &LocalServer::socketNotifierActivated);
55 if (server->listen(socket())) {
56 server->pauseAccepting();
58 qFatal(
"Failed to set server socket descriptor");
62 connect(engine, &ServerEngine::started, server, &LocalServer::resumeAccepting);
63 connect(engine, &ServerEngine::shutdown, server, &LocalServer::shutdown);
68void LocalServer::pauseAccepting()
70 auto notifier = socketDescriptorNotifier();
72 notifier->setEnabled(
false);
76void LocalServer::resumeAccepting()
79 m_socketNotifier->setEnabled(
true);
81 auto notifier = socketDescriptorNotifier();
83 notifier->setEnabled(
true);
88void LocalServer::incomingConnection(quintptr handle)
90 auto sock =
new LocalSocket(m_engine,
this);
91 sock->protoData = m_protocol->createData(sock);
94 sock->timeout =
false;
95 sock->proto->parse(sock, sock);
97 connect(sock, &LocalSocket::finished,
this, [
this, sock]() {
99 if (--m_processing == 0) {
100 m_engine->stopSocketTimeout();
104 if (Q_LIKELY(sock->setSocketDescriptor(qintptr(handle)))) {
105 sock->proto = m_protocol;
107 sock->serverAddress =
"localhost"_ba;
108 if (++m_processing) {
109 m_engine->startSocketTimeout();
116qintptr LocalServer::socket()
const
118 QSocketNotifier *notifier = socketDescriptorNotifier();
120 return notifier->
socket();
126void LocalServer::shutdown()
130 if (m_processing == 0) {
131 m_engine->serverShutdown();
134 for (
auto child : childrenL) {
137 connect(socket, &LocalSocket::finished,
this, [
this]() {
139 m_engine->serverShutdown();
142 m_engine->handleSocketShutdown(socket);
148void LocalServer::timeoutConnections()
152 for (
auto child : childrenL) {
155 if (socket->timeout) {
156 socket->connectionClose();
158 socket->timeout =
true;
165Protocol *LocalServer::protocol()
const
170QSocketNotifier *LocalServer::socketDescriptorNotifier()
const
172 QSocketNotifier *ret =
nullptr;
178 for (
auto child : childrenL) {
190void LocalServer::socketNotifierActivated()
196 uint length =
sizeof(sockaddr_un);
197 int connectedSocket =
198 cutelyst_safe_accept(
int(m_socket),
reinterpret_cast<sockaddr *
>(&addr), &length);
199 if (-1 != connectedSocket) {
200 incomingConnection(quintptr(connectedSocket));
205static inline int cutelyst_safe_accept(
int s,
struct sockaddr *addr, uint *addrlen,
int flags)
207 Q_ASSERT((flags & ~O_NONBLOCK) == 0);
210# ifdef QT_THREADSAFE_CLOEXEC
212 int sockflags = SOCK_CLOEXEC;
213 if (flags & O_NONBLOCK)
214 sockflags |= SOCK_NONBLOCK;
215# if defined(Q_OS_NETBSD)
216 fd = ::paccept(s, addr,
static_cast<socklen_t *
>(addrlen), NULL, sockflags);
218 fd = ::accept4(s, addr,
static_cast<socklen_t *
>(addrlen), sockflags);
222 fd = ::accept(s, addr,
static_cast<socklen_t *
>(addrlen));
226 ::fcntl(fd, F_SETFD, FD_CLOEXEC);
229 if (flags & O_NONBLOCK)
230 ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
237#include "moc_localserver.cpp"
The Cutelyst namespace holds all public Cutelyst API.
const QObjectList & children() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
T qobject_cast(QObject *object)
void activated(QSocketDescriptor socket, QSocketNotifier::Type type)
qintptr socket() const const