2 * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
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.
10 #include "anyp/PortCfg.h"
11 #include "client_side.h"
13 #include "comm/Read.h"
15 #include "error/SysErrorDetail.h"
18 #include "http/Stream.h"
20 #include "MasterXaction.h"
21 #include "servers/Server.h"
22 #include "SquidConfig.h"
23 #include "StatCounters.h"
26 Server::Server(const MasterXaction::Pointer
&xact
) :
27 AsyncJob("::Server"), // kids overwrite
28 clientConnection(xact
->tcpClient
),
29 transferProtocol(xact
->squidPort
->transport
),
30 port(xact
->squidPort
),
31 receivedFirstByte_(false)
35 Server::doneAll() const
37 // servers are not done while the connection is open
38 return !Comm::IsConnOpen(clientConnection
) &&
39 BodyProducer::doneAll();
45 // TODO: shuffle activity from ConnStateData
51 if (Comm::IsConnOpen(clientConnection
))
52 clientConnection
->close();
54 BodyProducer::swanSong();
61 Comm::ReadCancel(clientConnection
->fd
, reader
);
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.
72 Server::maybeMakeSpaceAvailable()
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
);
87 Server::readSomeData()
92 debugs(33, 4, clientConnection
<< ": reading request...");
94 // we can only read if there is more than 1 byte of space free
95 if (Config
.maxRequestBufferSize
- inBuf
.length() < 2)
98 typedef CommCbMemFunT
<Server
, CommIoCbParams
> Dialer
;
99 reader
= JobCallback(33, 5, Dialer
, this, Server::doClientRead
);
100 Comm::Read(clientConnection
, reader
);
104 Server::doClientRead(const CommIoCbParams
&io
)
106 debugs(33,5, io
.conn
);
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.");
116 assert(Comm::IsConnOpen(clientConnection
));
117 assert(io
.conn
->fd
== clientConnection
->fd
);
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
126 maybeMakeSpaceAvailable();
127 CommIoCbParams
rd(this); // will be expanded with ReadNow results
129 switch (Comm::ReadNow(rd
, inBuf
)) {
130 case Comm::INPROGRESS
:
133 debugs(33, 2, io
.conn
<< ": no data to process, " << xstrerr(rd
.xerrno
));
138 statCounter
.client_http
.kbytes_in
+= rd
.size
;
139 if (!receivedFirstByte_
)
141 // may comm_close or setReplyToError
142 if (!handleReadData())
145 /* Continue to process previously read data */
148 case Comm::ENDFILE
: // close detected by 0-byte read
149 debugs(33, 5, io
.conn
<< " closed?");
151 if (shouldCloseOnEof()) {
154 terminateAll(ERR_CLIENT_GONE
, lte
);
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");
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
168 /* Continue to process previously read data */
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
));
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
);
184 /** callback handling the Comm::Write completion
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.
191 Server::clientWriteDone(const CommIoCbParams
&io
)
193 debugs(33,5, io
.conn
);
194 Must(writer
!= nullptr);
197 /* Bail out quickly on Comm::ERR_CLOSING - close handlers will tidy up */
198 if (io
.flag
== Comm::ERR_CLOSING
|| !Comm::IsConnOpen(clientConnection
)) {
199 debugs(33,5, io
.conn
<< " closing Bailout.");
203 Must(io
.conn
->fd
== clientConnection
->fd
);
205 if (io
.flag
&& pipeline
.front())
206 pipeline
.front()->initiateClose("write failure");
208 afterClientWrite(io
.size
); // update state
209 writeSomeData(); // maybe schedules another write