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);
34void LocalServer::setProtocol(
Protocol *protocol)
36 m_protocol = protocol;
42 server->setProtocol(m_protocol);
43 server->m_engine = engine;
46 server->m_socket = socket();
48 server->m_socketNotifier->setEnabled(
false);
49 connect(server->m_socketNotifier,
52 &LocalServer::socketNotifierActivated);
54 if (server->listen(socket())) {
55 server->pauseAccepting();
57 qFatal(
"Failed to set server socket descriptor");
61 connect(engine, &ServerEngine::started, server, &LocalServer::resumeAccepting);
62 connect(engine, &ServerEngine::shutdown, server, &LocalServer::shutdown);
67void LocalServer::pauseAccepting()
69 auto notifier = socketDescriptorNotifier();
71 notifier->setEnabled(
false);
75void LocalServer::resumeAccepting()
80 auto notifier = socketDescriptorNotifier();
82 notifier->setEnabled(
true);
87void LocalServer::incomingConnection(quintptr handle)
90 sock->protoData = m_protocol->createData(sock);
93 sock->timeout =
false;
94 sock->proto->parse(sock, sock);
96 connect(sock, &LocalSocket::finished,
this, [
this, sock]() {
98 if (--m_processing == 0) {
99 m_engine->stopSocketTimeout();
103 if (Q_LIKELY(sock->setSocketDescriptor(qintptr(handle)))) {
104 sock->proto = m_protocol;
106 sock->serverAddress =
"localhost"_qba;
107 if (++m_processing) {
108 m_engine->startSocketTimeout();
115qintptr LocalServer::socket()
const
119 return notifier->
socket();
125void LocalServer::shutdown()
129 if (m_processing == 0) {
130 m_engine->serverShutdown();
133 for (
auto child : childrenL) {
134 auto socket = qobject_cast<LocalSocket *>(child);
136 connect(socket, &LocalSocket::finished,
this, [
this]() {
138 m_engine->serverShutdown();
141 m_engine->handleSocketShutdown(socket);
147void LocalServer::timeoutConnections()
151 for (
auto child : childrenL) {
152 auto socket = qobject_cast<LocalSocket *>(child);
154 if (socket->timeout) {
155 socket->connectionClose();
157 socket->timeout =
true;
164Protocol *LocalServer::protocol()
const
177 for (
auto child : childrenL) {
178 auto notifier = qobject_cast<QSocketNotifier *>(child);
189void LocalServer::socketNotifierActivated()
195 uint length =
sizeof(sockaddr_un);
196 int connectedSocket =
197 cutelyst_safe_accept(
int(m_socket),
reinterpret_cast<sockaddr *
>(&addr), &length);
198 if (-1 != connectedSocket) {
199 incomingConnection(quintptr(connectedSocket));
204static inline int cutelyst_safe_accept(
int s,
struct sockaddr *addr, uint *addrlen,
int flags)
206 Q_ASSERT((flags & ~O_NONBLOCK) == 0);
209# ifdef QT_THREADSAFE_CLOEXEC
211 int sockflags = SOCK_CLOEXEC;
212 if (flags & O_NONBLOCK)
213 sockflags |= SOCK_NONBLOCK;
214# if defined(Q_OS_NETBSD)
215 fd = ::paccept(s, addr,
static_cast<socklen_t *
>(addrlen), NULL, sockflags);
217 fd = ::accept4(s, addr,
static_cast<socklen_t *
>(addrlen), sockflags);
221 fd = ::accept(s, addr,
static_cast<socklen_t *
>(addrlen));
225 ::fcntl(fd, F_SETFD, FD_CLOEXEC);
228 if (flags & O_NONBLOCK)
229 ::fcntl(fd, F_SETFL, ::fcntl(fd, F_GETFL) | O_NONBLOCK);
236#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)
void activated(QSocketDescriptor socket, QSocketNotifier::Type type)
void setEnabled(bool enable)
qintptr socket() const const