]> git.ipfire.org Git - thirdparty/squid.git/blame - src/servers/Server.cc
Source Format Enforcement (#763)
[thirdparty/squid.git] / src / servers / Server.cc
CommitLineData
fcc444e3 1/*
f70aedc4 2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
fcc444e3
AJ
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9#include "squid.h"
10#include "anyp/PortCfg.h"
c6ae1627 11#include "client_side.h"
fcc444e3
AJ
12#include "comm.h"
13#include "comm/Read.h"
14#include "Debug.h"
83b053a0 15#include "error/SysErrorDetail.h"
fcc444e3
AJ
16#include "fd.h"
17#include "fde.h"
d3dddfb5 18#include "http/Stream.h"
83b053a0 19#include "LogTags.h"
fcc444e3
AJ
20#include "MasterXaction.h"
21#include "servers/Server.h"
22#include "SquidConfig.h"
23#include "StatCounters.h"
24#include "tools.h"
25
26Server::Server(const MasterXaction::Pointer &xact) :
27 AsyncJob("::Server"), // kids overwrite
28 clientConnection(xact->tcpClient),
29 transferProtocol(xact->squidPort->transport),
30 port(xact->squidPort),
2c391676 31 receivedFirstByte_(false)
fcc444e3
AJ
32{}
33
34bool
35Server::doneAll() const
36{
37 // servers are not done while the connection is open
38 return !Comm::IsConnOpen(clientConnection) &&
39 BodyProducer::doneAll();
40}
41
42void
43Server::start()
44{
45 // TODO: shuffle activity from ConnStateData
46}
47
48void
49Server::swanSong()
50{
51 if (Comm::IsConnOpen(clientConnection))
52 clientConnection->close();
53
54 BodyProducer::swanSong();
55}
56
57void
58Server::stopReading()
59{
60 if (reading()) {
61 Comm::ReadCancel(clientConnection->fd, reader);
62 reader = NULL;
63 }
64}
65
19e97cf0
AR
66/// Prepare inBuf for I/O. This method balances several conflicting desires:
67/// 1. Do not read too few bytes at a time.
68/// 2. Do not waste too much buffer space.
69/// 3. Do not [re]allocate or memmove the buffer too much.
70/// 4. Obey Config.maxRequestBufferSize limit.
71void
fcc444e3
AJ
72Server::maybeMakeSpaceAvailable()
73{
19e97cf0
AR
74 // The hard-coded parameters are arbitrary but seem reasonable.
75 // A careful study of Squid I/O and parsing patterns is needed to tune them.
76 SBufReservationRequirements requirements;
77 requirements.minSpace = 1024; // smaller I/Os are not worth their overhead
78 requirements.idealSpace = CLIENT_REQ_BUF_SZ; // we expect few larger I/Os
79 requirements.maxCapacity = Config.maxRequestBufferSize;
80 requirements.allowShared = true; // allow because inBuf is used immediately
81 inBuf.reserve(requirements);
82 if (!inBuf.spaceSize())
83 debugs(33, 4, "request buffer full: client_request_buffer_max_size=" << Config.maxRequestBufferSize);
fcc444e3
AJ
84}
85
86void
87Server::readSomeData()
88{
89 if (reading())
90 return;
91
92 debugs(33, 4, clientConnection << ": reading request...");
93
94 // we can only read if there is more than 1 byte of space free
95 if (Config.maxRequestBufferSize - inBuf.length() < 2)
96 return;
97
98 typedef CommCbMemFunT<Server, CommIoCbParams> Dialer;
99 reader = JobCallback(33, 5, Dialer, this, Server::doClientRead);
100 Comm::Read(clientConnection, reader);
101}
102
103void
104Server::doClientRead(const CommIoCbParams &io)
105{
106 debugs(33,5, io.conn);
107 Must(reading());
108 reader = NULL;
109
110 /* Bail out quickly on Comm::ERR_CLOSING - close handlers will tidy up */
111 if (io.flag == Comm::ERR_CLOSING) {
112 debugs(33,5, io.conn << " closing Bailout.");
113 return;
114 }
115
116 assert(Comm::IsConnOpen(clientConnection));
117 assert(io.conn->fd == clientConnection->fd);
118
119 /*
120 * Don't reset the timeout value here. The value should be
121 * counting Config.Timeout.request and applies to the request
122 * as a whole, not individual read() calls.
123 * Plus, it breaks our lame *HalfClosed() detection
124 */
125
126 maybeMakeSpaceAvailable();
127 CommIoCbParams rd(this); // will be expanded with ReadNow results
128 rd.conn = io.conn;
129 switch (Comm::ReadNow(rd, inBuf)) {
130 case Comm::INPROGRESS:
131
132 if (inBuf.isEmpty())
133 debugs(33, 2, io.conn << ": no data to process, " << xstrerr(rd.xerrno));
134 readSomeData();
135 return;
136
137 case Comm::OK:
138 statCounter.client_http.kbytes_in += rd.size;
139 if (!receivedFirstByte_)
140 receivedFirstByte();
141 // may comm_close or setReplyToError
142 if (!handleReadData())
143 return;
144
145 /* Continue to process previously read data */
146 break;
147
148 case Comm::ENDFILE: // close detected by 0-byte read
149 debugs(33, 5, io.conn << " closed?");
150
83b053a0
CT
151 if (shouldCloseOnEof()) {
152 LogTagsErrors lte;
153 lte.aborted = true;
154 terminateAll(ERR_CLIENT_GONE, lte);
fcc444e3
AJ
155 return;
156 }
157
158 /* It might be half-closed, we can't tell */
159 fd_table[io.conn->fd].flags.socket_eof = true;
160 commMarkHalfClosed(io.conn->fd);
161 fd_note(io.conn->fd, "half-closed");
162
163 /* There is one more close check at the end, to detect aborted
164 * (partial) requests. At this point we can't tell if the request
165 * is partial.
166 */
167
168 /* Continue to process previously read data */
169 break;
170
171 // case Comm::COMM_ERROR:
172 default: // no other flags should ever occur
173 debugs(33, 2, io.conn << ": got flag " << rd.flag << "; " << xstrerr(rd.xerrno));
83b053a0
CT
174 LogTagsErrors lte;
175 lte.timedout = rd.xerrno == ETIMEDOUT;
176 lte.aborted = !lte.timedout; // intentionally true for zero rd.xerrno
177 terminateAll(Error(ERR_CLIENT_GONE, SysErrorDetail::NewIfAny(rd.xerrno)), lte);
fcc444e3
AJ
178 return;
179 }
180
181 afterClientRead();
182}
183
21cd3227
AJ
184/** callback handling the Comm::Write completion
185 *
186 * Will call afterClientWrite(size_t) to sync the I/O state.
187 * Then writeSomeData() to initiate any followup writes that
188 * could be immediately done.
189 */
fcc444e3
AJ
190void
191Server::clientWriteDone(const CommIoCbParams &io)
192{
193 debugs(33,5, io.conn);
21cd3227
AJ
194 Must(writer != nullptr);
195 writer = nullptr;
fcc444e3
AJ
196
197 /* Bail out quickly on Comm::ERR_CLOSING - close handlers will tidy up */
21cd3227 198 if (io.flag == Comm::ERR_CLOSING || !Comm::IsConnOpen(clientConnection)) {
fcc444e3
AJ
199 debugs(33,5, io.conn << " closing Bailout.");
200 return;
201 }
202
21cd3227
AJ
203 Must(io.conn->fd == clientConnection->fd);
204
205 if (io.flag && pipeline.front())
206 pipeline.front()->initiateClose("write failure");
fcc444e3 207
21cd3227 208 afterClientWrite(io.size); // update state
fcc444e3
AJ
209 writeSomeData(); // maybe schedules another write
210}
15f8f9eb 211