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