]>
git.ipfire.org Git - thirdparty/squid.git/blob - src/whois.cc
2 * Copyright (C) 1996-2023 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.
9 /* DEBUG: section 75 WHOIS protocol */
13 #include "comm/Read.h"
14 #include "comm/Write.h"
15 #include "errorpage.h"
17 #include "HttpReply.h"
18 #include "HttpRequest.h"
19 #include "SquidConfig.h"
20 #include "StatCounters.h"
29 CBDATA_CLASS(WhoisState
);
32 void readReply(const Comm::ConnectionPointer
&, char *aBuffer
, size_t aBufferLength
, Comm::Flag flag
, int xerrno
);
33 void setReplyToOK(StoreEntry
*sentry
);
35 HttpRequest::Pointer request
;
36 FwdState::Pointer fwd
;
37 char buf
[BUFSIZ
+1]; /* readReply adds terminating NULL */
41 CBDATA_CLASS_INIT(WhoisState
);
43 static CLCB whoisClose
;
44 static CTCB whoisTimeout
;
45 static IOCB whoisReadReply
;
50 whoisWriteComplete(const Comm::ConnectionPointer
&, char *buf
, size_t, Comm::Flag
, int, void *)
56 whoisStart(FwdState
* fwd
)
58 WhoisState
*p
= new WhoisState
;
59 p
->request
= fwd
->request
;
60 p
->entry
= fwd
->entry
;
62 p
->dataWritten
= false;
64 p
->entry
->lock("whoisStart");
65 comm_add_close_handler(fwd
->serverConnection()->fd
, whoisClose
, p
);
67 size_t l
= p
->request
->url
.path().length() + 3;
68 char *buf
= (char *)xmalloc(l
);
70 const SBuf str_print
= p
->request
->url
.path().substr(1);
71 snprintf(buf
, l
, SQUIDSBUFPH
"\r\n", SQUIDSBUFPRINT(str_print
));
73 AsyncCall::Pointer writeCall
= commCbCall(5,5, "whoisWriteComplete",
74 CommIoCbPtrFun(whoisWriteComplete
, p
));
75 Comm::Write(fwd
->serverConnection(), buf
, strlen(buf
), writeCall
, nullptr);
76 AsyncCall::Pointer readCall
= commCbCall(5,4, "whoisReadReply",
77 CommIoCbPtrFun(whoisReadReply
, p
));
78 comm_read(fwd
->serverConnection(), p
->buf
, BUFSIZ
, readCall
);
79 AsyncCall::Pointer timeoutCall
= commCbCall(5, 4, "whoisTimeout",
80 CommTimeoutCbPtrFun(whoisTimeout
, p
));
81 commSetConnTimeout(fwd
->serverConnection(), Config
.Timeout
.read
, timeoutCall
);
87 whoisTimeout(const CommTimeoutCbParams
&io
)
89 WhoisState
*p
= static_cast<WhoisState
*>(io
.data
);
90 debugs(75, 3, io
.conn
<< ", URL " << p
->entry
->url());
95 whoisReadReply(const Comm::ConnectionPointer
&conn
, char *buf
, size_t len
, Comm::Flag flag
, int xerrno
, void *data
)
97 WhoisState
*p
= (WhoisState
*)data
;
98 p
->readReply(conn
, buf
, len
, flag
, xerrno
);
102 WhoisState::setReplyToOK(StoreEntry
*sentry
)
104 HttpReply
*reply
= new HttpReply
;
106 reply
->setHeaders(Http::scOkay
, "Gatewaying", "text/plain", -1, -1, -2);
107 reply
->sources
|= Http::Message::srcWhois
;
108 sentry
->replaceHttpReply(reply
);
112 WhoisState::readReply(const Comm::ConnectionPointer
&conn
, char *aBuffer
, size_t aBufferLength
, Comm::Flag flag
, int xerrno
)
114 /* Bail out early on Comm::ERR_CLOSING - close handlers will tidy up for us */
115 if (flag
== Comm::ERR_CLOSING
)
118 aBuffer
[aBufferLength
] = '\0';
119 debugs(75, 3, conn
<< " read " << aBufferLength
<< " bytes");
120 debugs(75, 5, "{" << aBuffer
<< "}");
122 // TODO: Honor delay pools.
124 // XXX: Update statCounter before bailing
125 if (!entry
->isAccepting()) {
126 debugs(52, 3, "terminating due to bad " << *entry
);
127 // TODO: Do not abuse connection for triggering cleanup.
132 if (flag
!= Comm::OK
) {
133 debugs(50, 2, conn
<< ": read failure: " << xstrerr(xerrno
));
135 if (ignoreErrno(xerrno
)) {
136 AsyncCall::Pointer call
= commCbCall(5,4, "whoisReadReply",
137 CommIoCbPtrFun(whoisReadReply
, this));
138 comm_read(conn
, aBuffer
, BUFSIZ
, call
);
140 const auto err
= new ErrorState(ERR_READ_ERROR
, Http::scInternalServerError
, fwd
->request
, fwd
->al
);
141 err
->xerrno
= xerrno
;
148 if (aBufferLength
> 0) {
152 statCounter
.server
.all
.kbytes_in
+= aBufferLength
;
153 statCounter
.server
.http
.kbytes_in
+= aBufferLength
;
155 /* No range support, we always grab it all */
157 entry
->append(aBuffer
, aBufferLength
);
160 AsyncCall::Pointer call
= commCbCall(5,4, "whoisReadReply",
161 CommIoCbPtrFun(whoisReadReply
, this));
162 comm_read(conn
, aBuffer
, BUFSIZ
, call
);
166 /* no bytes read. stop reading */
167 entry
->timestampsSet();
170 if (!entry
->makePublic())
171 entry
->makePrivate(true);
173 if (dataWritten
) // treat zero-length responses as incomplete
174 fwd
->markStoredReplyAsWhole("whois received/stored the entire response");
177 debugs(75, 3, "whoisReadReply: Done: " << entry
->url());
182 whoisClose(const CommCloseCbParams
¶ms
)
184 WhoisState
*p
= (WhoisState
*)params
.data
;
185 debugs(75, 3, "whoisClose: FD " << params
.fd
);
186 // We do not own a Connection. Assume that FwdState is also monitoring.
187 p
->entry
->unlock("whoisClose");