/*
* $Id: redirect.c,v 1.100.2.1 2008/05/04 23:23:13 hno Exp $
*
* DEBUG: section 85 Store URL Redirector
* AUTHOR: Adrian Chadd; based on redirect.c by Duane Wessels
*
* SQUID Web Proxy Cache http://www.squid-cache.org/
* ----------------------------------------------------------
*
* Squid is the result of efforts by numerous individuals from
* the Internet community; see the CONTRIBUTORS file for full
* details. Many organizations have provided support for Squid's
* development; see the SPONSORS file for full details. Squid is
* Copyrighted (C) 2001 by the Regents of the University of
* California; see the COPYRIGHT file for full details. Squid
* incorporates software developed and/or copyrighted by other
* sources; see the CREDITS file for full details.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
*
*/
#include "squid.h"
typedef struct {
void *data;
char *orig_url;
struct in_addr client_addr;
const char *client_ident;
const char *method_s;
RH *handler;
} redirectStateData;
static HLPCB redirectHandleReply;
static void redirectStateFree(redirectStateData * r);
static helper *redirectors = NULL;
static OBJH redirectStats;
static int n_bypassed = 0;
CBDATA_TYPE(redirectStateData);
static void
redirectHandleReply(void *data, char *reply)
{
redirectStateData *r = data;
int valid;
char *t;
debug(61, 5) ("redirectHandleReply: {%s}\n", reply ? reply : "<NULL>");
if (reply) {
if ((t = strchr(reply, ' ')))
*t = '\0';
if (*reply == '\0')
reply = NULL;
}
valid = cbdataValid(r->data);
cbdataUnlock(r->data);
if (valid)
r->handler(r->data, reply);
redirectStateFree(r);
}
static void
redirectStateFree(redirectStateData * r)
{
safe_free(r->orig_url);
cbdataFree(r);
}
static void
redirectStats(StoreEntry * sentry)
{
storeAppendPrintf(sentry, "Redirector Statistics:\n");
helperStats(sentry, redirectors);
if (Config.onoff.redirector_bypass)
storeAppendPrintf(sentry, "\nNumber of requests bypassed "
"because all redirectors were busy: %d\n", n_bypassed);
}
/**** PUBLIC FUNCTIONS ****/
void
redirectStart(clientHttpRequest * http, RH * handler, void *data)
{
ConnStateData *conn = http->conn;
redirectStateData *r = NULL;
const char *fqdn;
char *urlgroup = conn->port->urlgroup;
char buf[8192];
char claddr[20];
char myaddr[20];
assert(http);
assert(handler);
debug(61, 5) ("redirectStart: '%s'\n", http->uri);
if (Config.onoff.redirector_bypass && redirectors->stats.queue_size) {
/* Skip redirector if there is one request queued */
n_bypassed++;
handler(data, NULL);
return;
}
r = cbdataAlloc(redirectStateData);
r->orig_url = xstrdup(http->uri);
r->client_addr = conn->log_addr;
r->client_ident = NULL;
if (http->request->auth_user_request)
r->client_ident = authenticateUserRequestUsername(http->request->auth_user_request);
else if (http->request->extacl_user) {
r->client_ident = http->request->extacl_user;
}
if (!r->client_ident && conn->rfc931[0])
r->client_ident = conn->rfc931;
#if USE_SSL
if (!r->client_ident)
r->client_ident = sslGetUserEmail(fd_table[conn->fd].ssl);
#endif
if (!r->client_ident)
r->client_ident = dash_str;
r->method_s = RequestMethods[http->request->method].str;
r->handler = handler;
r->data = data;
r->USERAGENT = "FIND_ME_USER_AGENT_GOES_HERE";
cbdataLock(r->data);
if ((fqdn = fqdncache_gethostbyaddr(r->client_addr, 0)) == NULL)
fqdn = dash_str;
xstrncpy(claddr, inet_ntoa(r->client_addr), 20);
xstrncpy(myaddr, inet_ntoa(http->request->my_addr), 20);
snprintf(buf, 8191, "%s %s/%s %s %s %s myip=%s myport=%d %s",
r->orig_url,
claddr,
fqdn,
r->client_ident[0] ? rfc1738_escape(r->client_ident) : dash_str,
r->method_s,
urlgroup ? urlgroup : "-",
myaddr,
http->request->my_port,
r->orig_url);
debug(61, 6) ("redirectStart: sending '%s' to the helper\n", buf);
strcat(buf, "\n");
helperSubmit(redirectors, buf, redirectHandleReply, r);
}
void
redirectInit(void)
{
static int init = 0;
if (!Config.Program.url_rewrite.command)
return;
if (redirectors == NULL)
redirectors = helperCreate("url_rewriter");
redirectors->cmdline = Config.Program.url_rewrite.command;
redirectors->n_to_start = Config.Program.url_rewrite.children;
redirectors->concurrency = Config.Program.url_rewrite.concurrency;
redirectors->ipc_type = IPC_STREAM;
helperOpenServers(redirectors);
if (!init) {
cachemgrRegister("url_rewriter",
"URL Rewriter Stats",
redirectStats, 0, 1);
init = 1;
CBDATA_INIT_TYPE(redirectStateData);
}
}
void
redirectShutdown(void)
{
if (!redirectors)
return;
helperShutdown(redirectors);
if (!shutting_down)
return;
helperFree(redirectors);
redirectors = NULL;
}