Tsantilas Christos wrote:
>
>
> As an example of such changes I am attaching the rewritten
> parseHttpRequest, prepareTransparentURL and prepareAcceleratedURL
>
Sorry to all
the code I send in previous mail will not compile. I am sending it
again. Needs some more testing to be sure that it is OK....
int
internalCheckn(const char *urlpath,int size)
{
if(size<16)
return 0;
return (0 == strncmp(urlpath, "/squid-internal-", 16));
}
char *memstr(char *s,const char *pattern,int s_len){
int i,k;
int p_len=strlen(pattern);
for(i=0;i<=s_len-p_len;i++){
k=0;
while(k<p_len){
if(s[i+k] != pattern[k])
break;
k++;
}
if(k==p_len)
return s+i;
}
return NULL;
}
static void
prepareAcceleratedURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, char *url, int url_size, const char *req_hdr)
{
int vhost = conn->port->vhost;
int vport = conn->port->vport;
int uri_sz = 0, tmpsz = 0;
char *host,*s;
http->flags.accel = 1;
/* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */
if (url_size >= 15 && strncasecmp(url, "cache_object://", 15) == 0)
return; /* already in good shape */
if (*url != '/') {
if (conn->port->vhost)
return; /* already in good shape */
/* else we need to ignore the host name */
s = NULL;
s = memstr(url, "//", url_size);
if(s)
url_size -= ((s-url) + 2);
url = s + 2;
#if SHOULD_REJECT_UNKNOWN_URLS
if (!url)
return parseHttpRequestAbort(conn, "error:invalid-request");
#endif
if (url){
s=(char *)memchr(url,'/',url_size);
if(s)
url_size -= s-url;
url=s;
}
if (!url){
url = (char *) "/";
url_size = 1;
}
}
if (internalCheckn(url,url_size)) {
/* prepend our name & port */
s = (char *)xcalloc(url_size+1,1);
memcpy(s,url,url_size);
s[url_size]='\0';
http->uri = xstrdup(internalLocalUri(NULL, s));
xfree(s);
return;
}
if (vhost && (host = mime_get_header(req_hdr, "Host")) != NULL) {
uri_sz = url_size + 32 + Config.appendDomainLen +
strlen(host);
http->uri = (char *)xcalloc(uri_sz, 1);
tmpsz = snprintf(http->uri, uri_sz, "%s://%s",
conn->port->protocol, host);
} else if (conn->port->defaultsite) {
uri_sz = url_size + 32 + Config.appendDomainLen +
strlen(conn->port->defaultsite);
http->uri = (char *)xcalloc(uri_sz, 1);
tmpsz = snprintf(http->uri, uri_sz, "%s://%s",
conn->port->protocol, conn->port->defaultsite);
} else if (vport == -1) {
/* Put the local socket IP address as the hostname. */
uri_sz = url_size + 32 + Config.appendDomainLen;
http->uri = (char *)xcalloc(uri_sz, 1);
tmpsz = snprintf(http->uri, uri_sz, "%s://%s:%d",
http->getConn()->port->protocol,
inet_ntoa(http->getConn()->me.sin_addr),
ntohs(http->getConn()->me.sin_port));
} else if (vport > 0) {
/* Put the local socket IP address as the hostname, but static port */
uri_sz = url_size + 32 + Config.appendDomainLen;
http->uri = (char *)xcalloc(uri_sz, 1);
tmpsz = snprintf(http->uri, uri_sz, "%s://%s:%d",
http->getConn()->port->protocol,
inet_ntoa(http->getConn()->me.sin_addr),
vport);
}
else
return;
/*OK Append the url at the end of uri and we are OK....*/
uri_sz -= tmpsz;
url_size = XMIN(uri_sz - 1, url_size);
memcpy(http->uri+tmpsz, url , url_size);
http->uri[tmpsz+url_size] = '\0';
debug(33, 5) ("ACCEL VHOST REWRITE: '%s'\n", http->uri);
}
static void
prepareTransparentURL(ConnStateData::Pointer & conn, ClientHttpRequest *http, char *url, int url_size, const char *req_hdr)
{
char *host;
int uri_sz = 0, tmpsz = 0;
http->flags.transparent = 1;
if (*url != '/')
return; /* already in good shape */
/* BUG: Squid cannot deal with '*' URLs (RFC2616 5.1.2) */
if ((host = mime_get_header(req_hdr, "Host")) != NULL) {
uri_sz = url_size + 32 + Config.appendDomainLen +
strlen(host);
http->uri = (char *)xcalloc(uri_sz, 1);
tmpsz = snprintf(http->uri, uri_sz, "%s://%s",
conn->port->protocol, host);
} else {
/* Put the local socket IP address as the hostname. */
uri_sz = url_size + 32 + Config.appendDomainLen;
http->uri = (char *)xcalloc(uri_sz, 1);
tmpsz = snprintf(http->uri, uri_sz, "%s://%s:%d",
http->getConn()->port->protocol,
inet_ntoa(http->getConn()->me.sin_addr),
ntohs(http->getConn()->me.sin_port));
}
uri_sz -= tmpsz;
url_size = XMIN(uri_sz - 1, url_size);
memcpy(http->uri+tmpsz, url , url_size);
http->uri[tmpsz+url_size] = '\0';
debug(33, 5) ("TRANSPARENT HOST REWRITE: '%s'\n", http->uri);
}
/*
* parseHttpRequest()
*
* Returns
* NULL on incomplete requests
* a ClientSocketContext structure on success or failure.
* Sets result->flags.parsed_ok to 0 if failed to parse the request.
* Sets result->flags.parsed_ok to 1 if we have a good request.
*/
static ClientSocketContext *
parseHttpRequest(ConnStateData::Pointer & conn, HttpParser *hp, method_t * method_p, HttpVersion *http_ver)
{
char *url = NULL;
int url_size = 0;
char *req_hdr = NULL;
char *end;
size_t req_sz;
ClientHttpRequest *http;
ClientSocketContext *result;
StoreIOBuffer tempBuffer;
int r;
/* pre-set these values to make aborting simpler */
*method_p = METHOD_NONE;
/* Attempt to parse the first line; this'll define the method, url, version and header begin */
r = HttpParserParseReqLine(hp);
if (r == 0) {
debug(33, 5) ("Incomplete request, waiting for end of request line\n");
return NULL;
}
if (r == -1) {
return parseHttpRequestAbort(conn, "error:invalid-request");
}
/* Request line is valid here .. */
*http_ver = HttpVersion(hp->v_maj, hp->v_min);
/* This call scans the entire request, not just the headers */
if (hp->v_maj > 0) {
if ((req_sz = headersEnd(hp->buf, hp->bufsiz)) == 0) {
debug(33, 5) ("Incomplete request, waiting for end of headers\n");
return NULL;
}
} else {
debug(33, 3) ("parseHttpRequest: Missing HTTP identifier\n");
req_sz = HttpParserReqSz(hp);
}
/* We know the whole request is in hp->buf now */
assert(req_sz <= (size_t) hp->bufsiz);
/* Will the following be true with HTTP/0.9 requests? probably not .. */
/* So the rest of the code will need to deal with '0'-byte headers (ie, none, so don't try parsing em) */
assert(req_sz > 0);
hp->hdr_end = req_sz - 1;
hp->hdr_start = hp->req_end + 1;
/* Enforce max_request_size */
if (req_sz >= Config.maxRequestHeaderSize) {
debug(33, 5) ("parseHttpRequest: Too large request\n");
return parseHttpRequestAbort(conn, "error:request-too-large");
}
/* Set method_p */
*method_p = HttpRequestMethod(&hp->buf[hp->m_start], &hp->buf[hp->m_end]);
if (*method_p == METHOD_NONE) {
/* XXX need a way to say "this many character length string" */
debug(33, 1) ("clientParseRequestMethod: Unsupported method in request '%s'\n", hp->buf);
/* XXX where's the method set for this error? */
return parseHttpRequestAbort(conn, "error:unsupported-request-method");
}
/*
* Process headers after request line
* TODO: Use httpRequestParse here.
*/
/* XXX this code should be modified to take a const char * later! */
req_hdr = (char *) hp->buf + hp->req_end + 1;
debug(33, 3) ("parseHttpRequest: req_hdr = {%s}\n", req_hdr);
end = (char *) hp->buf + hp->hdr_end;
debug(33, 3) ("parseHttpRequest: end = {%s}\n", end);
if (strstr(req_hdr, "\r\r\n")) {
debug(33, 1) ("WARNING: suspicious HTTP request contains double CR\n");
return parseHttpRequestAbort(conn, "error:double-CR");
}
debug(33, 3) ("parseHttpRequest: prefix_sz = %d, req_line_sz = %d\n",
(int) HttpParserRequestLen(hp), HttpParserReqSz(hp));
/* Ok, all headers are received */
http = new ClientHttpRequest(conn);
http->req_sz = HttpParserRequestLen(hp);
result = ClientSocketContextNew(http);
tempBuffer.data = result->reqbuf;
tempBuffer.length = HTTP_REQBUF_SZ;
ClientStreamData newServer = new clientReplyContext(http);
ClientStreamData newClient = result;
clientStreamInit(&http->client_stream, clientGetMoreData, clientReplyDetach,
clientReplyStatus, newServer, clientSocketRecipient,
clientSocketDetach, newClient, tempBuffer);
debug(33, 5) ("parseHttpRequest: Request Header is\n%s\n",
(hp->buf) + hp->hdr_start);
url = (char *)(hp->buf + hp->u_start);
url_size = hp->u_end - hp->u_start + 1;
#if THIS_VIOLATES_HTTP_SPECS_ON_URL_TRANSFORMATION
/*url is not \0 terminated. this code if realy needed must rewritten*/
if ((t = strchr(url, '#'))) /* remove HTML anchors */
*t = '\0';
#endif
/* Rewrite the URL in transparent or accelerator mode */
if (conn->transparent()) {
prepareTransparentURL(conn, http, url, url_size, req_hdr);
} else if (conn->port->accel) {
prepareAcceleratedURL(conn, http, url, url_size, req_hdr);
} else if (internalCheckn(url, url_size)) {
/* prepend our name & port */
char *s = (char *)xmalloc(url_size + 16);
memcpy(s, url, url_size);
s[url_size] = '\0';
http->uri = xstrdup(internalLocalUri(NULL, s));
http->flags.accel = 1;
xfree(s);
}
if (!http->uri) {
/* No special rewrites have been applied above, use the
* requested url. may be rewritten later, so make extra room */
int u_sz = url_size + Config.appendDomainLen + 5;
http->uri = (char *)xcalloc(u_sz, 1);
memcpy(http->uri, url, url_size);
http->uri[url_size]='\0';
}
setLogUri(http, http->uri);
debug(33, 5) ("parseHttpRequest: Complete request received\n");
result->flags.parsed_ok = 1;
return result;
}
Received on Wed Feb 28 2007 - 12:04:38 MST
This archive was generated by hypermail pre-2.1.9 : Thu Mar 01 2007 - 12:00:02 MST