Read.cc
Go to the documentation of this file.
1/*
2 * Copyright (C) 1996-2023 The Squid Software Foundation and contributors
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/* DEBUG: section 05 Socket Functions */
10
11#include "squid.h"
12#include "comm.h"
13#include "comm/IoCallback.h"
14#include "comm/Loops.h"
15#include "comm/Read.h"
16#include "comm_internal.h"
17#include "CommCalls.h"
18#include "debug/Stream.h"
19#include "fd.h"
20#include "fde.h"
21#include "sbuf/SBuf.h"
22#include "SquidConfig.h"
23#include "StatCounters.h"
24
25// Does comm check this fd for read readiness?
26// Note that when comm is not monitoring, there can be a pending callback
27// call, which may resume comm monitoring once fired.
28bool
30{
31 assert(isOpen(fd) && COMMIO_FD_READCB(fd) != nullptr);
32 // Being active is usually the same as monitoring because we always
33 // start monitoring the FD when we configure Comm::IoCallback for I/O
34 // and we usually configure Comm::IoCallback for I/O when we starting
35 // monitoring a FD for reading.
36 return COMMIO_FD_READCB(fd)->active();
37}
38
39void
41{
42 // TODO: move comm_read_base() internals into here
43 // when comm_read() char* API is no longer needed
44 comm_read_base(conn, nullptr, 0, callback);
45}
46
55void
57{
58 debugs(5, 5, "comm_read, queueing read for " << conn << "; asynCall " << callback);
59
60 /* Make sure we are open and not closing */
62 assert(!fd_table[conn->fd].closing());
64
65 // Make sure we are either not reading or just passively monitoring.
66 // Active/passive conflicts are OK and simply cancel passive monitoring.
67 if (ccb->active()) {
68 // if the assertion below fails, we have an active comm_read conflict
69 assert(fd_table[conn->fd].halfClosedReader != nullptr);
71 assert(!ccb->active());
72 }
73 ccb->conn = conn;
74
75 /* Queue the read */
76 ccb->setCallback(Comm::IOCB_READ, callback, (char *)buf, nullptr, size);
78}
79
82{
83 /* Attempt a read */
85 SBuf::size_type sz = buf.spaceSize();
86 if (params.size > 0 && params.size < sz)
87 sz = params.size;
88 char *inbuf = buf.rawAppendStart(sz);
89 errno = 0;
90 const int retval = FD_READ_METHOD(params.conn->fd, inbuf, sz);
91 params.xerrno = errno;
92
93 debugs(5, 3, params.conn << ", size " << sz << ", retval " << retval << ", errno " << params.xerrno);
94
95 if (retval > 0) { // data read most common case
96 buf.rawAppendFinish(inbuf, retval);
97 fd_bytes(params.conn->fd, retval, FD_READ);
98 params.flag = Comm::OK;
99 params.size = retval;
100
101 } else if (retval == 0) { // remote closure (somewhat less) common
102 // Note - read 0 == socket EOF, which is a valid read.
103 params.flag = Comm::ENDFILE;
104 params.size = 0;
105
106 } else if (retval < 0) { // connection errors are worst-case
107 debugs(5, 3, params.conn << " Comm::COMM_ERROR: " << xstrerr(params.xerrno));
108 if (ignoreErrno(params.xerrno))
109 params.flag = Comm::INPROGRESS;
110 else
111 params.flag = Comm::COMM_ERROR;
112 params.size = 0;
113 }
114
115 return params.flag;
116}
117
127void
128Comm::HandleRead(int fd, void *data)
129{
130 Comm::IoCallback *ccb = (Comm::IoCallback *) data;
131
132 assert(data == COMMIO_FD_READCB(fd));
133 assert(ccb->active());
134
135 // Without a buffer, just call back.
136 // The callee may ReadMore() to get the data.
137 if (!ccb->buf) {
138 ccb->finish(Comm::OK, 0);
139 return;
140 }
141
142 /* For legacy callers : Attempt a read */
143 // Keep in sync with Comm::ReadNow()!
145 int xerrno = errno = 0;
146 int retval = FD_READ_METHOD(fd, ccb->buf, ccb->size);
147 xerrno = errno;
148 debugs(5, 3, "FD " << fd << ", size " << ccb->size << ", retval " << retval << ", errno " << xerrno);
149
150 /* See if we read anything */
151 /* Note - read 0 == socket EOF, which is a valid read */
152 if (retval >= 0) {
153 fd_bytes(fd, retval, FD_READ);
154 ccb->offset = retval;
155 ccb->finish(Comm::OK, 0);
156 return;
157 } else if (retval < 0 && !ignoreErrno(xerrno)) {
158 debugs(5, 3, "comm_read_try: scheduling Comm::COMM_ERROR");
159 ccb->offset = 0;
160 ccb->finish(Comm::COMM_ERROR, xerrno);
161 return;
162 };
163
164 /* Nope, register for some more IO */
166}
167
180void
181comm_read_cancel(int fd, IOCB *callback, void *data)
182{
183 if (!isOpen(fd)) {
184 debugs(5, 4, "fails: FD " << fd << " closed");
185 return;
186 }
187
189 // TODO: is "active" == "monitors FD"?
190 if (!cb->active()) {
191 debugs(5, 4, "fails: FD " << fd << " inactive");
192 return;
193 }
194
196 Call *call = dynamic_cast<Call*>(cb->callback.getRaw());
197 if (!call) {
198 debugs(5, 4, "fails: FD " << fd << " lacks callback");
199 return;
200 }
201
202 call->cancel("old comm_read_cancel");
203
204 typedef CommIoCbParams Params;
205 const Params &params = GetCommParams<Params>(cb->callback);
206
207 /* Ok, we can be reasonably sure we won't lose any data here! */
208 assert(call->dialer.handler == callback);
209 assert(params.data == data);
210
211 /* Delete the callback */
212 cb->cancel("old comm_read_cancel");
213
214 /* And the IO event */
215 Comm::SetSelect(fd, COMM_SELECT_READ, nullptr, nullptr, 0);
216}
217
218void
220{
221 callback->cancel("comm_read_cancel");
222
223 if (!isOpen(fd)) {
224 debugs(5, 4, "fails: FD " << fd << " closed");
225 return;
226 }
227
229
230 if (!cb->active()) {
231 debugs(5, 4, "fails: FD " << fd << " inactive");
232 return;
233 }
234
235 AsyncCall::Pointer call = cb->callback;
236
237 /* Ok, we can be reasonably sure we won't lose any data here! */
238 assert(call == callback);
239
240 /* Delete the callback */
241 cb->cancel("comm_read_cancel");
242
243 /* And the IO event */
244 Comm::SetSelect(fd, COMM_SELECT_READ, nullptr, nullptr, 0);
245}
246
247time_t
248Comm::MortalReadTimeout(const time_t startTime, const time_t lifetimeLimit)
249{
250 if (lifetimeLimit > 0) {
251 const time_t timeUsed = (squid_curtime > startTime) ? (squid_curtime - startTime) : 0;
252 const time_t timeLeft = (lifetimeLimit > timeUsed) ? (lifetimeLimit - timeUsed) : 0;
253 return min(::Config.Timeout.read, timeLeft);
254 } else
256}
257
void IOCB(const Comm::ConnectionPointer &conn, char *, size_t size, Comm::Flag flag, int xerrno, void *data)
Definition: CommCalls.h:34
#define COMMIO_FD_READCB(fd)
Definition: IoCallback.h:78
int size
Definition: ModDevPoll.cc:75
time_t squid_curtime
Definition: stub_libtime.cc:20
void comm_read_cancel(int fd, IOCB *callback, void *data)
Definition: Read.cc:181
void comm_read_base(const Comm::ConnectionPointer &conn, char *buf, int size, AsyncCall::Pointer &callback)
Definition: Read.cc:56
class SquidConfig Config
Definition: SquidConfig.cc:12
StatCounters statCounter
Definition: StatCounters.cc:12
int conn
the current server connection FD
Definition: Transport.cc:26
#define assert(EX)
Definition: assert.h:17
bool cancel(const char *reason)
Definition: AsyncCall.cc:56
int xerrno
The last errno to occur. non-zero if flag is Comm::COMM_ERROR.
Definition: CommCalls.h:83
Comm::Flag flag
comm layer result status.
Definition: CommCalls.h:82
Comm::ConnectionPointer conn
Definition: CommCalls.h:80
Details about a particular Comm IO callback event.
Definition: IoCallback.h:30
void setCallback(iocb_type type, AsyncCall::Pointer &cb, char *buf, FREE *func, int sz)
Definition: IoCallback.cc:55
bool active() const
Definition: IoCallback.h:45
AsyncCall::Pointer callback
Definition: IoCallback.h:34
void finish(Comm::Flag code, int xerrn)
finish the IO operation immediately and schedule the callback with the current state.
Definition: IoCallback.cc:110
void cancel(const char *reason)
Actively cancel the given callback.
Definition: IoCallback.cc:82
Comm::ConnectionPointer conn
Definition: IoCallback.h:33
C * getRaw() const
Definition: RefCount.h:89
Definition: SBuf.h:94
char * rawAppendStart(size_type anticipatedSize)
Definition: SBuf.cc:136
size_type spaceSize() const
Definition: SBuf.h:393
MemBlob::size_type size_type
Definition: SBuf.h:96
void rawAppendFinish(const char *start, size_type actualSize)
Definition: SBuf.cc:144
time_t read
Definition: SquidConfig.h:112
struct SquidConfig::@93 Timeout
struct StatCounters::@130 syscalls
struct StatCounters::@130::@135 sock
void commStopHalfClosedMonitor(int const fd)
stop waiting for possibly half-closed connection to close
Definition: comm.cc:1637
int ignoreErrno(int ierrno)
Definition: comm.cc:1440
bool isOpen(const int fd)
Definition: comm.cc:88
A const & min(A const &lhs, A const &rhs)
#define debugs(SECTION, LEVEL, CONTENT)
Definition: Stream.h:194
#define COMM_SELECT_READ
Definition: defines.h:24
@ FD_READ
Definition: enums.h:23
void fd_bytes(int fd, int len, unsigned int type)
Definition: fd.cc:226
#define fd_table
Definition: fde.h:189
int FD_READ_METHOD(int fd, char *buf, int len)
Definition: fde.h:194
bool MonitorsRead(int fd)
whether the FD socket is being monitored for read
Definition: Read.cc:29
void ReadCancel(int fd, AsyncCall::Pointer &callback)
Cancel the read pending on FD. No action if none pending.
Definition: Read.cc:219
@ IOCB_READ
Definition: IoCallback.h:24
void Read(const Comm::ConnectionPointer &conn, AsyncCall::Pointer &callback)
Definition: Read.cc:40
bool IsConnOpen(const Comm::ConnectionPointer &conn)
Definition: Connection.cc:27
Flag
Definition: Flag.h:15
@ OK
Definition: Flag.h:16
@ ENDFILE
Definition: Flag.h:26
@ COMM_ERROR
Definition: Flag.h:17
@ INPROGRESS
Definition: Flag.h:21
time_t MortalReadTimeout(const time_t startTime, const time_t lifetimeLimit)
maximum read delay for readers with limited lifetime
Definition: Read.cc:248
PF HandleRead
callback handler to process an FD which is available for reading
Definition: Read.cc:128
void SetSelect(int, unsigned int, PF *, void *, time_t)
Mark an FD to be watched for its IO status.
Definition: ModDevPoll.cc:223
Comm::Flag ReadNow(CommIoCbParams &params, SBuf &buf)
Definition: Read.cc:81
static CTCB Timeout
Definition: Ident.cc:74
const char * xstrerr(int error)
Definition: xstrerror.cc:83

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors