]> git.ipfire.org Git - thirdparty/squid.git/blob - src/redirect.cc
Merge form trunk
[thirdparty/squid.git] / src / redirect.cc
1
2 /*
3 * $Id$
4 *
5 * DEBUG: section 61 Redirector
6 * AUTHOR: Duane Wessels
7 *
8 * SQUID Web Proxy Cache http://www.squid-cache.org/
9 * ----------------------------------------------------------
10 *
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.
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.
24 *
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.
29 *
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
32 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
33 *
34 */
35
36 #include "squid.h"
37 #include "auth/UserRequest.h"
38 #include "comm/Connection.h"
39 #include "mgr/Registration.h"
40 #include "Store.h"
41 #include "fde.h"
42 #include "client_side_request.h"
43 #include "acl/Checklist.h"
44 #include "HttpRequest.h"
45 #include "client_side.h"
46 #include "helper.h"
47 #include "rfc1738.h"
48
49 typedef struct {
50 void *data;
51 char *orig_url;
52
53 Ip::Address client_addr;
54 const char *client_ident;
55 const char *method_s;
56 RH *handler;
57 } redirectStateData;
58
59 static HLPCB redirectHandleReply;
60 static void redirectStateFree(redirectStateData * r);
61 static helper *redirectors = NULL;
62 static OBJH redirectStats;
63 static int n_bypassed = 0;
64 CBDATA_TYPE(redirectStateData);
65
66 static void
67 redirectHandleReply(void *data, char *reply)
68 {
69 redirectStateData *r = static_cast<redirectStateData *>(data);
70 char *t;
71 void *cbdata;
72 debugs(61, 5, "redirectHandleRead: {" << (reply && *reply != '\0' ? reply : "<NULL>") << "}");
73
74 if (reply) {
75 if ((t = strchr(reply, ' ')))
76 *t = '\0';
77
78 if (*reply == '\0')
79 reply = NULL;
80 }
81
82 if (cbdataReferenceValidDone(r->data, &cbdata))
83 r->handler(cbdata, reply);
84
85 redirectStateFree(r);
86 }
87
88 static void
89 redirectStateFree(redirectStateData * r)
90 {
91 safe_free(r->orig_url);
92 cbdataFree(r);
93 }
94
95 static void
96 redirectStats(StoreEntry * sentry)
97 {
98 if (redirectors == NULL) {
99 storeAppendPrintf(sentry, "No redirectors defined\n");
100 return;
101 }
102
103 helperStats(sentry, redirectors, "Redirector Statistics");
104
105 if (Config.onoff.redirector_bypass)
106 storeAppendPrintf(sentry, "\nNumber of requests bypassed "
107 "because all redirectors were busy: %d\n", n_bypassed);
108 }
109
110 /**** PUBLIC FUNCTIONS ****/
111
112 void
113 redirectStart(ClientHttpRequest * http, RH * handler, void *data)
114 {
115 ConnStateData * conn = http->getConn();
116 redirectStateData *r = NULL;
117 const char *fqdn;
118 char buf[8192];
119 char claddr[MAX_IPSTRLEN];
120 char myaddr[MAX_IPSTRLEN];
121 assert(http);
122 assert(handler);
123 debugs(61, 5, "redirectStart: '" << http->uri << "'");
124
125 if (Config.onoff.redirector_bypass && redirectors->stats.queue_size) {
126 /* Skip redirector if there is one request queued */
127 n_bypassed++;
128 handler(data, NULL);
129 return;
130 }
131
132 r = cbdataAlloc(redirectStateData);
133 r->orig_url = xstrdup(http->uri);
134 if (conn != NULL)
135 r->client_addr = conn->log_addr;
136 else
137 r->client_addr.SetNoAddr();
138 r->client_ident = NULL;
139
140 if (http->request->auth_user_request != NULL)
141 r->client_ident = http->request->auth_user_request->username();
142 else if (http->request->extacl_user.defined()) {
143 r->client_ident = http->request->extacl_user.termedBuf();
144 }
145
146 if (!r->client_ident && (conn != NULL && conn->rfc931[0]))
147 r->client_ident = conn->rfc931;
148
149 #if USE_SSL
150
151 if (!r->client_ident && conn != NULL && Comm::IsConnOpen(conn->clientConn))
152 r->client_ident = sslGetUserEmail(fd_table[conn->clientConn->fd].ssl);
153
154 #endif
155
156 if (!r->client_ident)
157 r->client_ident = dash_str;
158
159 r->method_s = RequestMethodStr(http->request->method);
160
161 r->handler = handler;
162
163 r->data = cbdataReference(data);
164
165 if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
166 fqdn = dash_str;
167
168 snprintf(buf, 8192, "%s %s/%s %s %s myip=%s myport=%d\n",
169 r->orig_url,
170 r->client_addr.NtoA(claddr,MAX_IPSTRLEN),
171 fqdn,
172 r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
173 r->method_s,
174 http->request->my_addr.NtoA(myaddr,MAX_IPSTRLEN),
175 http->request->my_addr.GetPort());
176
177 helperSubmit(redirectors, buf, redirectHandleReply, r);
178 }
179
180 static void
181 redirectRegisterWithCacheManager(void)
182 {
183 Mgr::RegisterAction("redirector", "URL Redirector Stats", redirectStats, 0, 1);
184 }
185
186 void
187 redirectInit(void)
188 {
189 static int init = 0;
190
191 redirectRegisterWithCacheManager();
192
193 if (!Config.Program.redirect)
194 return;
195
196 if (redirectors == NULL)
197 redirectors = new helper("redirector");
198
199 redirectors->cmdline = Config.Program.redirect;
200
201 redirectors->childs = Config.redirectChildren;
202
203 redirectors->ipc_type = IPC_STREAM;
204
205 helperOpenServers(redirectors);
206
207 if (!init) {
208 init = 1;
209 CBDATA_INIT_TYPE(redirectStateData);
210 }
211 }
212
213 void
214 redirectShutdown(void)
215 {
216 if (!redirectors)
217 return;
218
219 helperShutdown(redirectors);
220
221 if (!shutting_down)
222 return;
223
224 delete redirectors;
225 redirectors = NULL;
226 }