cutelyst 4.3.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
tcpserver.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2016-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "tcpserver.h"
6
7#include "protocol.h"
8#include "protocolhttp.h"
9#include "server.h"
10#include "socket.h"
11
12#include <Cutelyst/Engine>
13
14#include <QDateTime>
15#include <QLoggingCategory>
16
17Q_LOGGING_CATEGORY(C_SERVER_TCP, "cutelyst.server.tcp", QtWarningMsg)
18
19using namespace Cutelyst;
20
21TcpServer::TcpServer(const QByteArray &serverAddress,
22 Protocol *protocol,
23 Server *wsgi,
24 QObject *parent)
25 : QTcpServer(parent)
26 , m_serverAddress(serverAddress)
27 , m_wsgi(wsgi)
28 , m_protocol(protocol)
29{
30 m_engine = qobject_cast<ServerEngine *>(parent);
31
32 if (m_wsgi->tcpNodelay()) {
33 m_socketOptions.push_back({QAbstractSocket::LowDelayOption, 1});
34 }
35 if (m_wsgi->soKeepalive()) {
36 m_socketOptions.push_back({QAbstractSocket::KeepAliveOption, 1});
37 }
38 if (m_wsgi->socketSndbuf() != -1) {
39 m_socketOptions.push_back(
40 {QAbstractSocket::SendBufferSizeSocketOption, m_wsgi->socketSndbuf()});
41 }
42 if (m_wsgi->socketRcvbuf() != -1) {
43 m_socketOptions.push_back(
44 {QAbstractSocket::ReceiveBufferSizeSocketOption, m_wsgi->socketRcvbuf()});
45 }
46}
47
48void TcpServer::incomingConnection(qintptr handle)
49{
50 auto sock = new TcpSocket(m_engine, this);
51 sock->serverAddress = m_serverAddress;
52 sock->protoData = m_protocol->createData(sock);
53
54 connect(sock, &QIODevice::readyRead, [sock] {
55 sock->timeout = false;
56 sock->proto->parse(sock, sock);
57 });
58 connect(sock, &TcpSocket::finished, this, [this, sock] {
59 sock->deleteLater();
60 if (--m_processing == 0) {
61 m_engine->stopSocketTimeout();
62 }
63 });
64
65 if (Q_LIKELY(sock->setSocketDescriptor(
67 sock->proto = m_protocol;
68
69 sock->remoteAddress = sock->peerAddress();
70 sock->remotePort = sock->peerPort();
71 sock->protoData->setupNewConnection(sock);
72
73 for (const auto &opt : m_socketOptions) {
74 sock->setSocketOption(opt.first, opt.second);
75 }
76
77 if (++m_processing) {
78 m_engine->startSocketTimeout();
79 }
80 } else {
81 delete sock;
82 }
83}
84
85void TcpServer::shutdown()
86{
87 close();
88
89 if (m_processing == 0) {
90 m_engine->serverShutdown();
91 } else {
92 const auto childrenL = children();
93 for (auto child : childrenL) {
94 auto socket = qobject_cast<TcpSocket *>(child);
95 if (socket) {
96 connect(socket, &TcpSocket::finished, this, [this]() {
97 if (m_processing == 0) {
98 m_engine->serverShutdown();
99 }
100 });
101 m_engine->handleSocketShutdown(socket);
102 }
103 }
104 }
105}
106
107void TcpServer::timeoutConnections()
108{
109 if (m_processing) {
110 const auto childrenL = children();
111 for (auto child : childrenL) {
112 auto socket = qobject_cast<TcpSocket *>(child);
113 if (socket && !socket->processing &&
114 socket->state() == QAbstractSocket::ConnectedState) {
115 if (socket->timeout) {
116 qCInfo(C_SERVER_TCP) << "timing out connection"
117 << socket->peerAddress().toString() << socket->peerPort();
118 socket->connectionClose();
119 } else {
120 socket->timeout = true;
121 }
122 }
123 }
124 }
125}
126
127Protocol *TcpServer::protocol() const
128{
129 return m_protocol;
130}
131
132void TcpServer::setProtocol(Protocol *protocol)
133{
134 m_protocol = protocol;
135}
136
137#include "moc_tcpserver.cpp"
Implements a web server.
Definition server.h:60
The Cutelyst namespace holds all public Cutelyst API.
void readyRead()
const QObjectList & children() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
void close()