]> git.ipfire.org Git - thirdparty/squid.git/blame - src/whois.cc
Fix concurrency support in stateless helpers: Parse multiple replies correctly.
[thirdparty/squid.git] / src / whois.cc
CommitLineData
77b32a34 1
af6691cc 2/*
af6691cc 3 * DEBUG: section 75 WHOIS protocol
4 * AUTHOR: Duane Wessels, Kostas Anagnostakis
5 *
2b6662ba 6 * SQUID Web Proxy Cache http://www.squid-cache.org/
e25c139f 7 * ----------------------------------------------------------
af6691cc 8 *
2b6662ba 9 * Squid is the result of efforts by numerous individuals from
10 * the Internet community; see the CONTRIBUTORS file for full
11 * details. Many organizations have provided support for Squid's
12 * development; see the SPONSORS file for full details. Squid is
13 * Copyrighted (C) 2001 by the Regents of the University of
14 * California; see the COPYRIGHT file for full details. Squid
15 * incorporates software developed and/or copyrighted by other
16 * sources; see the CREDITS file for full details.
af6691cc 17 *
18 * This program is free software; you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation; either version 2 of the License, or
21 * (at your option) any later version.
26ac0430 22 *
af6691cc 23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
26ac0430 27 *
af6691cc 28 * You should have received a copy of the GNU General Public License
29 * along with this program; if not, write to the Free Software
cbdec147 30 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
e25c139f 31 *
af6691cc 32 */
33
582c2af2
FC
34#include "squid.h"
35#include "comm.h"
ec41b64c 36#include "comm/Write.h"
aa839030 37#include "errorpage.h"
528b2c61 38#include "HttpReply.h"
924f73bc 39#include "HttpRequest.h"
a2ac85d9 40#include "HttpRequest.h"
b6b6f466 41#include "forward.h"
4d5904f7 42#include "SquidConfig.h"
e4f1fdae 43#include "StatCounters.h"
582c2af2 44#include "Store.h"
4e540555 45#include "tools.h"
af6691cc 46
21d845b1
FC
47#if HAVE_ERRNO_H
48#include <errno.h>
49#endif
50
af6691cc 51#define WHOIS_PORT 43
52
62e76326 53class WhoisState
54{
55
528b2c61 56public:
b6b6f466 57 ~WhoisState();
e0d28505 58 void readReply(const Comm::ConnectionPointer &, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno);
e053c141 59 void setReplyToOK(StoreEntry *sentry);
af6691cc 60 StoreEntry *entry;
190154cf 61 HttpRequest *request;
b6b6f466 62 FwdState::Pointer fwd;
5bac8e33 63 char buf[BUFSIZ+1]; /* readReply adds terminating NULL */
528b2c61 64 bool dataWritten;
65};
af6691cc 66
575d05c4 67static CLCB whoisClose;
8d77a37c 68static CTCB whoisTimeout;
c4b7a5a9 69static IOCB whoisReadReply;
af6691cc 70
71/* PUBLIC */
72
28c60158 73CBDATA_TYPE(WhoisState);
74
b6b6f466 75WhoisState::~WhoisState()
76{
77 fwd = NULL; // refcounted
78}
79
e6546865 80static void
e0d28505 81whoisWriteComplete(const Comm::ConnectionPointer &, char *buf, size_t size, comm_err_t flag, int xerrno, void *data)
e6546865 82{
62e76326 83 xfree(buf);
e6546865 84}
85
af6691cc 86void
db1cd23c 87whoisStart(FwdState * fwd)
af6691cc 88{
28c60158 89 WhoisState *p;
af6691cc 90 char *buf;
91 size_t l;
28c60158 92 CBDATA_INIT_TYPE(WhoisState);
72711e31 93 p = cbdataAlloc(WhoisState);
db1cd23c 94 p->request = fwd->request;
95 p->entry = fwd->entry;
96 p->fwd = fwd;
5bac8e33 97 p->dataWritten = false;
34266cde 98
3d0ac046 99 p->entry->lock();
e0d28505 100 comm_add_close_handler(fwd->serverConnection()->fd, whoisClose, p);
34266cde 101
528b2c61 102 l = p->request->urlpath.size() + 3;
34266cde 103
e6ccf245 104 buf = (char *)xmalloc(l);
34266cde 105
2c1fd837
FC
106 String str_print=p->request->urlpath.substr(1,p->request->urlpath.size());
107 snprintf(buf, l, SQUIDSTRINGPH"\r\n", SQUIDSTRINGPRINT(str_print));
34266cde 108
abd8f140 109 AsyncCall::Pointer writeCall = commCbCall(5,5, "whoisWriteComplete",
dc49061a 110 CommIoCbPtrFun(whoisWriteComplete, p));
abd8f140
AJ
111 Comm::Write(fwd->serverConnection(), buf, strlen(buf), writeCall, NULL);
112 AsyncCall::Pointer readCall = commCbCall(5,4, "whoisReadReply",
dc49061a 113 CommIoCbPtrFun(whoisReadReply, p));
abd8f140 114 comm_read(fwd->serverConnection(), p->buf, BUFSIZ, readCall);
8d77a37c 115 AsyncCall::Pointer timeoutCall = commCbCall(5, 4, "whoisTimeout",
dc49061a 116 CommTimeoutCbPtrFun(whoisTimeout, p));
8d77a37c 117 commSetConnTimeout(fwd->serverConnection(), Config.Timeout.read, timeoutCall);
af6691cc 118}
119
120/* PRIVATE */
121
122static void
8d77a37c 123whoisTimeout(const CommTimeoutCbParams &io)
af6691cc 124{
8d77a37c
AJ
125 WhoisState *p = static_cast<WhoisState *>(io.data);
126 debugs(75, 3, HERE << io.conn << ", URL " << p->entry->url());
127 io.conn->close();
af6691cc 128}
129
130static void
e0d28505 131whoisReadReply(const Comm::ConnectionPointer &conn, char *buf, size_t len, comm_err_t flag, int xerrno, void *data)
af6691cc 132{
e6ccf245 133 WhoisState *p = (WhoisState *)data;
e0d28505 134 p->readReply(conn, buf, len, flag, xerrno);
528b2c61 135}
136
137void
e053c141 138WhoisState::setReplyToOK(StoreEntry *sentry)
528b2c61 139{
06a5ae20 140 HttpReply *reply = new HttpReply;
e053c141 141 sentry->buffer();
11992b6f 142 reply->setHeaders(HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2);
e053c141 143 sentry->replaceHttpReply(reply);
528b2c61 144}
145
146void
e0d28505 147WhoisState::readReply(const Comm::ConnectionPointer &conn, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno)
528b2c61 148{
c4b7a5a9 149 /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */
58c0b17d 150 if (flag == COMM_ERR_CLOSING)
c4b7a5a9 151 return;
c4b7a5a9 152
e053c141 153 aBuffer[aBufferLength] = '\0';
e0d28505 154 debugs(75, 3, HERE << conn << " read " << aBufferLength << " bytes");
e053c141 155 debugs(75, 5, "{" << aBuffer << "}");
62e76326 156
58c0b17d 157 if (flag != COMM_OK) {
e0d28505 158 debugs(50, 2, HERE << conn << ": read failure: " << xstrerror() << ".");
62e76326 159
160 if (ignoreErrno(errno)) {
1b76e6c1
AJ
161 AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply",
162 CommIoCbPtrFun(whoisReadReply, this));
163 comm_read(conn, aBuffer, BUFSIZ, call);
6cae5db1 164 } else {
913524f0 165 ErrorState *err = new ErrorState(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, fwd->request);
129fe2a1 166 err->xerrno = xerrno;
b6b6f466 167 fwd->fail(err);
80463bb4 168 conn->close();
62e76326 169 }
58c0b17d
AJ
170 return;
171 }
62e76326 172
58c0b17d
AJ
173 if (aBufferLength > 0) {
174 if (!dataWritten)
175 setReplyToOK(entry);
62e76326 176
e4f1fdae
FC
177 kb_incr(&(statCounter.server.all.kbytes_in), aBufferLength);
178 kb_incr(&(statCounter.server.http.kbytes_in), aBufferLength);
62e76326 179
58c0b17d
AJ
180 /* No range support, we always grab it all */
181 dataWritten = true;
182 entry->append(aBuffer, aBufferLength);
183 entry->flush();
62e76326 184
abd8f140
AJ
185 AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply",
186 CommIoCbPtrFun(whoisReadReply, this));
187 comm_read(conn, aBuffer, BUFSIZ, call);
58c0b17d 188 return;
abd8f140 189 }
62e76326 190
58c0b17d
AJ
191 /* no bytes read. stop reading */
192 entry->timestampsSet();
193 entry->flush();
194
195 if (!EBIT_TEST(entry->flags, RELEASE_REQUEST))
196 entry->setPublicKey();
197
198 fwd->complete();
199 debugs(75, 3, "whoisReadReply: Done: " << entry->url());
1b76e6c1 200 conn->close();
af6691cc 201}
202
203static void
575d05c4 204whoisClose(const CommCloseCbParams &params)
af6691cc 205{
575d05c4
AJ
206 WhoisState *p = (WhoisState *)params.data;
207 debugs(75, 3, "whoisClose: FD " << params.fd);
97b5e68f 208 p->entry->unlock();
af6691cc 209 cbdataFree(p);
210}