]> git.ipfire.org Git - thirdparty/squid.git/blame - src/comm/Read.cc
Cleanup: remove useless dead #include lines
[thirdparty/squid.git] / src / comm / Read.cc
CommitLineData
7e66d5e2 1/*
ef57eb7b 2 * Copyright (C) 1996-2016 The Squid Software Foundation and contributors
bbc27441
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.
7e66d5e2 7 */
bbc27441
AJ
8
9/* DEBUG: section 05 Socket Functions */
10
7e66d5e2
AJ
11#include "squid.h"
12#include "comm.h"
7e66d5e2
AJ
13#include "comm/IoCallback.h"
14#include "comm/Loops.h"
15#include "comm/Read.h"
470b1598
A
16#include "comm_internal.h"
17#include "CommCalls.h"
7e66d5e2
AJ
18#include "Debug.h"
19#include "fd.h"
20#include "fde.h"
65e41a45 21#include "sbuf/SBuf.h"
7e66d5e2 22#include "StatCounters.h"
7e66d5e2
AJ
23
24// Does comm check this fd for read readiness?
25// Note that when comm is not monitoring, there can be a pending callback
26// call, which may resume comm monitoring once fired.
27bool
28Comm::MonitorsRead(int fd)
29{
670b31a6 30 assert(isOpen(fd) && COMMIO_FD_READCB(fd) != NULL);
7e66d5e2
AJ
31 // Being active is usually the same as monitoring because we always
32 // start monitoring the FD when we configure Comm::IoCallback for I/O
33 // and we usually configure Comm::IoCallback for I/O when we starting
34 // monitoring a FD for reading.
35 return COMMIO_FD_READCB(fd)->active();
36}
37
38void
39Comm::Read(const Comm::ConnectionPointer &conn, AsyncCall::Pointer &callback)
40{
41 // TODO: move comm_read_base() internals into here
42 // when comm_read() char* API is no longer needed
43 comm_read_base(conn, NULL, 0, callback);
44}
45
46/**
47 * Queue a read.
48 * If a buffer is given the callback is scheduled when the read
49 * completes, on error, or on file descriptor close.
50 *
51 * If no buffer (NULL) is given the callback is scheduled when
52 * the socket FD is ready for a read(2)/recv(2).
53 */
54void
55comm_read_base(const Comm::ConnectionPointer &conn, char *buf, int size, AsyncCall::Pointer &callback)
56{
57 debugs(5, 5, "comm_read, queueing read for " << conn << "; asynCall " << callback);
58
59 /* Make sure we are open and not closing */
60 assert(Comm::IsConnOpen(conn));
61 assert(!fd_table[conn->fd].closing());
62 Comm::IoCallback *ccb = COMMIO_FD_READCB(conn->fd);
63
64 // Make sure we are either not reading or just passively monitoring.
65 // Active/passive conflicts are OK and simply cancel passive monitoring.
66 if (ccb->active()) {
67 // if the assertion below fails, we have an active comm_read conflict
68 assert(fd_table[conn->fd].halfClosedReader != NULL);
69 commStopHalfClosedMonitor(conn->fd);
70 assert(!ccb->active());
71 }
72 ccb->conn = conn;
73
74 /* Queue the read */
75 ccb->setCallback(Comm::IOCB_READ, callback, (char *)buf, NULL, size);
76 Comm::SetSelect(conn->fd, COMM_SELECT_READ, Comm::HandleRead, ccb, 0);
77}
78
c8407295 79Comm::Flag
7e66d5e2
AJ
80Comm::ReadNow(CommIoCbParams &params, SBuf &buf)
81{
82 /* Attempt a read */
83 ++ statCounter.syscalls.sock.reads;
983de17b
AJ
84 SBuf::size_type sz = buf.spaceSize();
85 if (params.size > 0 && params.size < sz)
86 sz = params.size;
183b70d5 87 char *inbuf = buf.rawSpace(sz);
7e66d5e2 88 errno = 0;
183b70d5 89 const int retval = FD_READ_METHOD(params.conn->fd, inbuf, sz);
7e66d5e2
AJ
90 params.xerrno = errno;
91
92 debugs(5, 3, params.conn << ", size " << sz << ", retval " << retval << ", errno " << params.xerrno);
93
94 if (retval > 0) { // data read most common case
183b70d5 95 buf.append(inbuf, retval);
7e66d5e2 96 fd_bytes(params.conn->fd, retval, FD_READ);
c8407295 97 params.flag = Comm::OK;
7e66d5e2
AJ
98 params.size = retval;
99
100 } else if (retval == 0) { // remote closure (somewhat less) common
101 // Note - read 0 == socket EOF, which is a valid read.
c8407295 102 params.flag = Comm::ENDFILE;
7e66d5e2
AJ
103
104 } else if (retval < 0) { // connection errors are worst-case
4ee57cbe 105 debugs(5, 3, params.conn << " Comm::COMM_ERROR: " << xstrerr(params.xerrno));
7e66d5e2 106 if (ignoreErrno(params.xerrno))
c8407295 107 params.flag = Comm::INPROGRESS;
7e66d5e2 108 else
4ee57cbe 109 params.flag = Comm::COMM_ERROR;
7e66d5e2
AJ
110 }
111
112 return params.flag;
113}
114
115/**
116 * Handle an FD which is ready for read(2).
117 *
118 * If there is no provided buffer to fill call the callback.
119 *
120 * Otherwise attempt a read into the provided buffer.
121 * If the read attempt succeeds or fails, call the callback.
122 * Else, wait for another IO notification.
123 */
124void
125Comm::HandleRead(int fd, void *data)
126{
127 Comm::IoCallback *ccb = (Comm::IoCallback *) data;
128
129 assert(data == COMMIO_FD_READCB(fd));
130 assert(ccb->active());
131
183b70d5
AJ
132 // Without a buffer, just call back.
133 // The callee may ReadMore() to get the data.
7e66d5e2 134 if (!ccb->buf) {
c8407295 135 ccb->finish(Comm::OK, 0);
7e66d5e2
AJ
136 return;
137 }
138
139 /* For legacy callers : Attempt a read */
140 // Keep in sync with Comm::ReadNow()!
141 ++ statCounter.syscalls.sock.reads;
5dc67d58 142 int xerrno = errno = 0;
7e66d5e2 143 int retval = FD_READ_METHOD(fd, ccb->buf, ccb->size);
5dc67d58
AD
144 xerrno = errno;
145 debugs(5, 3, "FD " << fd << ", size " << ccb->size << ", retval " << retval << ", errno " << xerrno);
7e66d5e2
AJ
146
147 /* See if we read anything */
148 /* Note - read 0 == socket EOF, which is a valid read */
149 if (retval >= 0) {
150 fd_bytes(fd, retval, FD_READ);
151 ccb->offset = retval;
5dc67d58 152 ccb->finish(Comm::OK, 0);
7e66d5e2 153 return;
5dc67d58 154 } else if (retval < 0 && !ignoreErrno(xerrno)) {
4ee57cbe 155 debugs(5, 3, "comm_read_try: scheduling Comm::COMM_ERROR");
7e66d5e2 156 ccb->offset = 0;
5dc67d58 157 ccb->finish(Comm::COMM_ERROR, xerrno);
7e66d5e2
AJ
158 return;
159 };
160
7e66d5e2
AJ
161 /* Nope, register for some more IO */
162 Comm::SetSelect(fd, COMM_SELECT_READ, Comm::HandleRead, data, 0);
163}
164
165/**
166 * Cancel a pending read. Assert that we have the right parameters,
167 * and that there are no pending read events!
168 *
169 * XXX: We do not assert that there are no pending read events and
170 * with async calls it becomes even more difficult.
171 * The whole interface should be reworked to do callback->cancel()
172 * instead of searching for places where the callback may be stored and
173 * updating the state of those places.
174 *
175 * AHC Don't call the comm handlers?
176 */
177void
178comm_read_cancel(int fd, IOCB *callback, void *data)
179{
180 if (!isOpen(fd)) {
181 debugs(5, 4, "fails: FD " << fd << " closed");
182 return;
183 }
184
185 Comm::IoCallback *cb = COMMIO_FD_READCB(fd);
186 // TODO: is "active" == "monitors FD"?
187 if (!cb->active()) {
188 debugs(5, 4, "fails: FD " << fd << " inactive");
189 return;
190 }
191
192 typedef CommCbFunPtrCallT<CommIoCbPtrFun> Call;
193 Call *call = dynamic_cast<Call*>(cb->callback.getRaw());
194 if (!call) {
195 debugs(5, 4, "fails: FD " << fd << " lacks callback");
196 return;
197 }
198
199 call->cancel("old comm_read_cancel");
200
201 typedef CommIoCbParams Params;
202 const Params &params = GetCommParams<Params>(cb->callback);
203
204 /* Ok, we can be reasonably sure we won't lose any data here! */
205 assert(call->dialer.handler == callback);
206 assert(params.data == data);
207
208 /* Delete the callback */
209 cb->cancel("old comm_read_cancel");
210
211 /* And the IO event */
212 Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
213}
214
215void
216Comm::ReadCancel(int fd, AsyncCall::Pointer &callback)
217{
218 callback->cancel("comm_read_cancel");
219
220 if (!isOpen(fd)) {
221 debugs(5, 4, "fails: FD " << fd << " closed");
222 return;
223 }
224
225 Comm::IoCallback *cb = COMMIO_FD_READCB(fd);
226
227 if (!cb->active()) {
228 debugs(5, 4, "fails: FD " << fd << " inactive");
229 return;
230 }
231
232 AsyncCall::Pointer call = cb->callback;
233
234 /* Ok, we can be reasonably sure we won't lose any data here! */
235 assert(call == callback);
236
237 /* Delete the callback */
238 cb->cancel("comm_read_cancel");
239
240 /* And the IO event */
241 Comm::SetSelect(fd, COMM_SELECT_READ, NULL, NULL, 0);
242}
f53969cc 243