]>
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 | ||
36 | #include "squid.h" | |
ec41b64c | 37 | #include "comm/Write.h" |
aa839030 | 38 | #include "errorpage.h" |
e6ccf245 | 39 | #include "Store.h" |
528b2c61 | 40 | #include "HttpReply.h" |
924f73bc | 41 | #include "HttpRequest.h" |
e6546865 | 42 | #include "comm.h" |
a2ac85d9 | 43 | #include "HttpRequest.h" |
b6b6f466 | 44 | #include "forward.h" |
af6691cc | 45 | |
46 | #define WHOIS_PORT 43 | |
47 | ||
62e76326 | 48 | class WhoisState |
49 | { | |
50 | ||
528b2c61 | 51 | public: |
b6b6f466 | 52 | ~WhoisState(); |
e0d28505 | 53 | void readReply(const Comm::ConnectionPointer &, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno); |
e053c141 | 54 | void setReplyToOK(StoreEntry *sentry); |
af6691cc | 55 | StoreEntry *entry; |
190154cf | 56 | HttpRequest *request; |
b6b6f466 | 57 | FwdState::Pointer fwd; |
5bac8e33 | 58 | char buf[BUFSIZ+1]; /* readReply adds terminating NULL */ |
528b2c61 | 59 | bool dataWritten; |
60 | }; | |
af6691cc | 61 | |
62 | static PF whoisClose; | |
63 | static PF whoisTimeout; | |
c4b7a5a9 | 64 | static IOCB whoisReadReply; |
af6691cc | 65 | |
66 | /* PUBLIC */ | |
67 | ||
28c60158 | 68 | CBDATA_TYPE(WhoisState); |
69 | ||
b6b6f466 | 70 | WhoisState::~WhoisState() |
71 | { | |
72 | fwd = NULL; // refcounted | |
73 | } | |
74 | ||
e6546865 | 75 | static void |
e0d28505 | 76 | whoisWriteComplete(const Comm::ConnectionPointer &, char *buf, size_t size, comm_err_t flag, int xerrno, void *data) |
e6546865 | 77 | { |
62e76326 | 78 | xfree(buf); |
e6546865 | 79 | } |
80 | ||
af6691cc | 81 | void |
db1cd23c | 82 | whoisStart(FwdState * fwd) |
af6691cc | 83 | { |
28c60158 | 84 | WhoisState *p; |
af6691cc | 85 | char *buf; |
86 | size_t l; | |
28c60158 | 87 | CBDATA_INIT_TYPE(WhoisState); |
72711e31 | 88 | p = cbdataAlloc(WhoisState); |
db1cd23c | 89 | p->request = fwd->request; |
90 | p->entry = fwd->entry; | |
91 | p->fwd = fwd; | |
5bac8e33 | 92 | p->dataWritten = false; |
34266cde | 93 | |
3d0ac046 | 94 | p->entry->lock(); |
e0d28505 | 95 | comm_add_close_handler(fwd->serverConnection()->fd, whoisClose, p); |
34266cde | 96 | |
528b2c61 | 97 | l = p->request->urlpath.size() + 3; |
34266cde | 98 | |
e6ccf245 | 99 | buf = (char *)xmalloc(l); |
34266cde | 100 | |
2c1fd837 FC |
101 | String str_print=p->request->urlpath.substr(1,p->request->urlpath.size()); |
102 | snprintf(buf, l, SQUIDSTRINGPH"\r\n", SQUIDSTRINGPRINT(str_print)); | |
34266cde | 103 | |
abd8f140 AJ |
104 | AsyncCall::Pointer writeCall = commCbCall(5,5, "whoisWriteComplete", |
105 | CommIoCbPtrFun(whoisWriteComplete, p)); | |
106 | Comm::Write(fwd->serverConnection(), buf, strlen(buf), writeCall, NULL); | |
107 | AsyncCall::Pointer readCall = commCbCall(5,4, "whoisReadReply", | |
108 | CommIoCbPtrFun(whoisReadReply, p)); | |
109 | comm_read(fwd->serverConnection(), p->buf, BUFSIZ, readCall); | |
e0d28505 | 110 | commSetTimeout(fwd->serverConnection()->fd, Config.Timeout.read, whoisTimeout, p); |
af6691cc | 111 | } |
112 | ||
113 | /* PRIVATE */ | |
114 | ||
115 | static void | |
116 | whoisTimeout(int fd, void *data) | |
117 | { | |
e6ccf245 | 118 | WhoisState *p = (WhoisState *)data; |
bf8fe701 | 119 | debugs(75, 1, "whoisTimeout: " << p->entry->url() ); |
af6691cc | 120 | whoisClose(fd, p); |
121 | } | |
122 | ||
123 | static void | |
e0d28505 | 124 | whoisReadReply(const Comm::ConnectionPointer &conn, char *buf, size_t len, comm_err_t flag, int xerrno, void *data) |
af6691cc | 125 | { |
e6ccf245 | 126 | WhoisState *p = (WhoisState *)data; |
e0d28505 | 127 | p->readReply(conn, buf, len, flag, xerrno); |
528b2c61 | 128 | } |
129 | ||
130 | void | |
e053c141 | 131 | WhoisState::setReplyToOK(StoreEntry *sentry) |
528b2c61 | 132 | { |
06a5ae20 | 133 | HttpReply *reply = new HttpReply; |
e053c141 | 134 | sentry->buffer(); |
11992b6f | 135 | reply->setHeaders(HTTP_OK, "Gatewaying", "text/plain", -1, -1, -2); |
e053c141 | 136 | sentry->replaceHttpReply(reply); |
528b2c61 | 137 | } |
138 | ||
139 | void | |
e0d28505 | 140 | WhoisState::readReply(const Comm::ConnectionPointer &conn, char *aBuffer, size_t aBufferLength, comm_err_t flag, int xerrno) |
528b2c61 | 141 | { |
c4b7a5a9 | 142 | int do_next_read = 0; |
143 | ||
144 | /* Bail out early on COMM_ERR_CLOSING - close handlers will tidy up for us */ | |
62e76326 | 145 | |
c4b7a5a9 | 146 | if (flag == COMM_ERR_CLOSING) { |
147 | return; | |
148 | } | |
149 | ||
e053c141 | 150 | aBuffer[aBufferLength] = '\0'; |
e0d28505 | 151 | debugs(75, 3, HERE << conn << " read " << aBufferLength << " bytes"); |
e053c141 | 152 | debugs(75, 5, "{" << aBuffer << "}"); |
62e76326 | 153 | |
e053c141 | 154 | if (flag == COMM_OK && aBufferLength > 0) { |
62e76326 | 155 | if (!dataWritten) |
156 | setReplyToOK(entry); | |
157 | ||
e053c141 | 158 | kb_incr(&statCounter.server.all.kbytes_in, aBufferLength); |
62e76326 | 159 | |
e053c141 | 160 | kb_incr(&statCounter.server.http.kbytes_in, aBufferLength); |
62e76326 | 161 | |
162 | /* No range support, we always grab it all */ | |
5bac8e33 | 163 | dataWritten = true; |
62e76326 | 164 | |
e053c141 | 165 | entry->append(aBuffer, aBufferLength); |
62e76326 | 166 | |
3900307b | 167 | entry->flush(); |
b66315e4 | 168 | |
c4b7a5a9 | 169 | do_next_read = 1; |
e053c141 | 170 | } else if (flag != COMM_OK || aBufferLength < 0) { |
e0d28505 | 171 | debugs(50, 2, HERE << conn << ": read failure: " << xstrerror() << "."); |
62e76326 | 172 | |
173 | if (ignoreErrno(errno)) { | |
c4b7a5a9 | 174 | do_next_read = 1; |
6cae5db1 | 175 | } else { |
62e76326 | 176 | ErrorState *err; |
2cc81f1f | 177 | err = errorCon(ERR_READ_ERROR, HTTP_INTERNAL_SERVER_ERROR, fwd->request); |
62e76326 | 178 | err->xerrno = errno; |
b6b6f466 | 179 | fwd->fail(err); |
80463bb4 | 180 | conn->close(); |
c4b7a5a9 | 181 | do_next_read = 0; |
62e76326 | 182 | } |
abdacbb5 | 183 | } else { |
3900307b | 184 | entry->timestampsSet(); |
185 | entry->flush(); | |
62e76326 | 186 | |
187 | if (!EBIT_TEST(entry->flags, RELEASE_REQUEST)) | |
d88e3c49 | 188 | entry->setPublicKey(); |
62e76326 | 189 | |
b6b6f466 | 190 | fwd->complete(); |
bf8fe701 | 191 | debugs(75, 3, "whoisReadReply: Done: " << entry->url() ); |
80463bb4 | 192 | conn->close(); |
c4b7a5a9 | 193 | do_next_read = 0; |
af6691cc | 194 | } |
62e76326 | 195 | |
abd8f140 AJ |
196 | if (do_next_read) { |
197 | AsyncCall::Pointer call = commCbCall(5,4, "whoisReadReply", | |
198 | CommIoCbPtrFun(whoisReadReply, this)); | |
199 | comm_read(conn, aBuffer, BUFSIZ, call); | |
200 | } | |
af6691cc | 201 | } |
202 | ||
203 | static void | |
204 | whoisClose(int fd, void *data) | |
205 | { | |
e6ccf245 | 206 | WhoisState *p = (WhoisState *)data; |
bf8fe701 | 207 | debugs(75, 3, "whoisClose: FD " << fd); |
97b5e68f | 208 | p->entry->unlock(); |
af6691cc | 209 | cbdataFree(p); |
210 | } |